package cc.rengu.igas.momp.core.service.trans;

import cc.rengu.igas.momp.common.constant.CommonConstant;
import cc.rengu.igas.momp.common.dao.*;
import cc.rengu.igas.momp.common.dao.impl.*;
import cc.rengu.igas.momp.common.entity.*;
import cc.rengu.igas.momp.common.enums.*;
import cc.rengu.igas.momp.common.model.bean.JsonMfdMcOrderRemark;
import cc.rengu.igas.momp.common.util.JsonOperation;
import cc.rengu.igas.momp.common.util.MompDateUtil;
import cc.rengu.igas.momp.facade.bean.TxnDataRegulationBean;
import cc.rengu.igas.momp.facade.request.TxnDataRegulationRequest;
import cc.rengu.igas.momp.facade.response.TxnDataRegulationResponse;
import cc.rengu.jradp.mods.dbs.Database;
import cc.rengu.oltp.service.base.RadpService;
import cc.rengu.oltp.service.common.constant.AppConfigConstant;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.OltpRpcdEnum;
import cc.rengu.oltp.service.common.enums.TransStatusEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.utility.util.*;
import cc.rengu.utility.base.StringUtil;
import com.alibaba.fastjson.JSONObject;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 交易调账接口实现
 *
 * @author Jinan Liu
 * @version 1.0.0
 * @since 2020/6/14 10:22
 */

public class TxnDataRegulationService extends RadpService {

    /**
     * 法人机构号
     */
    private String globalInstId;
    /**
     * 调账交易流水号
     */
    private String globalTraceNo;
    /**
     * 调账交易时间戳
     */
    private String globalTimeStamp;
    /**
     * 调账交易日期
     */
    private String globalTxnDate;
    /**
     * 退货类型
     */
    private int refundType;
    /**
     * 调账交易类型
     */
    private String txnFlag;
    /**
     * 待调账交易订单流水
     */
    private TMTxnOrder tmTxnOrderOld;
    /**
     * 待调账交易关联订单流水
     */
    private TMTxnOrder tmTxnOrderPay;
    /**
     * 本笔交易订单流水
     */
    private TMTxnOrder tmTxnOrderNew;
    /**
     * 本笔交易订单明细
     */
    private List<TMTxnOrderDet> tmTxnOrderDetListNew;
    /**
     * 本笔交易对客户营销活动单日统计表
     */
    private List<TMStat2CDay> tmStat2CDayList;
    /**
     * 本笔交易对客户营销活动商户单日统计表
     */
    private List<TMStat2CMchntDay> tmStat2CMchntDayList;
    /**
     * 本笔交易手续费减免活动单日统计表
     */
    private List<TMStatMfdDay> tmStatMfdDayList;
    /**
     * 本笔交易手续费减免活动商户单日统计表
     */
    private List<TMStatMfdMchntDay> tmStatMfdMchntDayList;
    /**
     * 是否是最后一笔退货的调账
     */
    private Boolean isLastDeal = false;
    /**
     * 本笔交易手续费优惠金额累计
     */
    private List<TMStatMfdDay> statMfdDayList;

    @Override
    protected int bizInit(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizProcess(String s, int i) {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();

        try {

            TxnDataRegulationRequest txnDataRegulationRequest = new TxnDataRegulationRequest();
            ConvertUtil.convertOutput(txnDataRegulationRequest);

            TxnDataRegulationResponse txnDataRegulationResponse = new TxnDataRegulationResponse();
            txnDataRegulationResponse.setHeader(txnDataRegulationRequest.getHeader());
            BizResponse<TxnDataRegulationResponse> bizResponse = new BizResponse<>();
            bizResponse.setResult(txnDataRegulationResponse);

            /* 初始化应答报文 */
            initResponse(txnDataRegulationRequest, txnDataRegulationResponse);

            // 服务调用
            BizResponse<TxnDataRegulationResponse> bizResponseNew = txnDataRegulation(xmlTreeUtil, txnDataRegulationRequest, txnDataRegulationResponse);

            ConvertUtil.convertInput(bizResponseNew.getResult());

        } catch (BizException e) {
            try {
                xmlTreeUtil
                        .setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, e.getCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, e.getMessage());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        } catch (Exception e) {
            rglog.error(StringUtil.ExceptionToString(e));
            try {
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_CODE, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespCode());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.RESP_DESC, OltpRpcdEnum.OLTP_PROCESS_ERROR.getRespDesc());
                xmlTreeUtil.setXmlTreeStringValue(CommonConstant.KEY_RESPDESC, e.getMessage());
            } catch (Exception e1) {
                rglog.error(StringUtil.ExceptionToString(e1));
            }
        }

        return CommonConstant.PROCESS_SUCCESS;
    }

    @Override
    protected int bizTerminate(String s) {
        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 交易调账
     *
     * @param xmlTreeUtil               内部XML树
     * @param txnDataRegulationRequest  交易调账接口请求对象
     * @param txnDataRegulationResponse 交易调账接口应答对象
     * @return cc.rengu.oltp.service.model.BizResponse<cc.rengu.igas.momp.facade.response.TxnDataRegulationResponse> 交易调账接口应答对象
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/6/15 10:07
     */
    private BizResponse<TxnDataRegulationResponse> txnDataRegulation(XmlTreeUtil xmlTreeUtil, TxnDataRegulationRequest txnDataRegulationRequest, TxnDataRegulationResponse txnDataRegulationResponse) throws Exception {

        BizResponse<TxnDataRegulationResponse> bizResponse = new BizResponse<>();

        String dbPoolName;
        DbsUtil dbsUtil = null;

        String instId = txnDataRegulationRequest.getHeader().getInstId();

        int returnCode;

        /* 取调账交易明细 */
        TxnDataRegulationBean txnDataRegulationBean = txnDataRegulationRequest.getOrderDetail();
        String origTransDate = txnDataRegulationBean.getOrigTxnDate();
        String origTraceNo = txnDataRegulationBean.getOrigTraceNo();

        /* 取原交易流水 */
        TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();
        tmTxnOrderOld = tmTxnOrderMapper.selectTransactionOrderInfo(instId, origTransDate, origTraceNo);
        if (null == tmTxnOrderOld) {
            rglog.error("未取到法人机构<{}>在<{}>的流水号<{}>的原始交易信息!", instId, origTransDate, origTraceNo);
            throw new BizException(RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespCode(), RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespDesc());
        }

        /* 判断是不是重复调账 */
        if (BizStatusEnum.PROCESS_REGULATED.getBizStatusCode().equals(tmTxnOrderOld.getBizStatus())) {
            rglog.error("原交易已调账,不可重复调账!");
            throw new BizException(RespCodeEnum.DUPLICATE_TRANSACTION_ERROR.getRespCode(), RespCodeEnum.DUPLICATE_TRANSACTION_ERROR.getRespDesc());
        }

        /* 判断该笔支付交易是否可以调账 */
        if (!TransStatusEnum.TRANS_SUCC.getStatus().equals(tmTxnOrderOld.getTransStatus()) && !BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode().equals(tmTxnOrderOld.getBizStatus())) {
            /* 原交易状态异常,不可调账 */
            rglog.error("法人机构<{}>在<{}>的流水号<{}>的交易状态异常,不可调账! TRANS_STATUS=<{}>, BIZ_STATUS=<{}>", instId, origTransDate, origTraceNo, tmTxnOrderOld.getTransStatus(), tmTxnOrderOld.getBizStatus());
            throw new BizException(RespCodeEnum.DUPLICATE_TRANSACTION_ERROR.getRespCode(), RespCodeEnum.DUPLICATE_TRANSACTION_ERROR.getRespDesc());
        }

        /* 取原交易流水明细 */
        TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        List<TMTxnOrderDet> tmTxnOrderDetList = tmTxnOrderDetMapper.selectOriginalTransactionOrderDetailListInfo(instId, origTransDate, origTraceNo);
        if (null == tmTxnOrderDetList || tmTxnOrderDetList.isEmpty()) {
            rglog.error("未取到法人机构<{}>在<{}>的流水号<{}>的原始交易明细信息!", instId, origTransDate, origTraceNo);
            throw new BizException(RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespCode(), RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespDesc());
        }

        /* 判断如何处理 */
        checkOriginalTxnType(tmTxnOrderOld);

        /* 开启数据库事务 */
        dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(AppConfigConstant.DATABASE_CONF_NODE, AppConfigConstant.MOMP_POOL_NAME);
        String corporation = xmlTreeUtil.getXmlTreeStringValue(AppParamConstant.CORPORATION);
        if (null != corporation && !corporation.isEmpty()) {
            String dbPoolCashNode = corporation.trim() + AppParamConstant.DATABASE_CONF_NODE;
            dbPoolName = XmlConfigUtil.getXmlConfigCacheKeyValue(dbPoolCashNode, AppConfigConstant.MOMP_POOL_NAME);
        }
        dbsUtil = new DbsUtil(dbPoolName);
        dbsUtil.dbsBeginTransaction();

        try {

            /* 支付或退货调账 */
            switch (txnFlag) {
                case "PAYMENT":
                    returnCode = processPaymentRegulation(tmTxnOrderDetList);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                        rglog.error("处理支付类交易调账流程失败!所有数据库操作回滚!");
                        dbsUtil.dbsEndTransaction(false);
                        throw new BizException(RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespCode(), RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespDesc());
                    }

                    break;
                case "REFUND":

                    /* 取本笔待调账交易的原始消费交易的订单流水 */
                    tmTxnOrderPay = tmTxnOrderMapper.selectTransactionOrderInfo(instId, tmTxnOrderOld.getOrigTxnDate(), tmTxnOrderOld.getOrigSysSeqNum());
                    if (null == tmTxnOrderPay) {
                        rglog.error("未取到法人机构<{}>在<{}>的流水号<{}>的原始支付交易信息!", instId, tmTxnOrderOld.getOrigTxnDate(), tmTxnOrderOld.getOrigSysSeqNum());
                        dbsUtil.dbsEndTransaction(false);
                        throw new BizException(RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespCode(), RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespDesc());
                    }

                    /* 取本笔待调账交易的原始消费交易的订单明细 */
                    List<TMTxnOrderDet> tmTxnOrderDetListPay = tmTxnOrderDetMapper.selectOriginalTransactionOrderDetailListInfo(instId, tmTxnOrderPay.getTxnDate(), tmTxnOrderPay.getFrontSeqNum());
                    if (null == tmTxnOrderDetListPay || tmTxnOrderDetListPay.isEmpty()) {
                        rglog.error("未取到法人机构<{}>在<{}>的流水号<{}>的原始支付交易明细信息!", instId, tmTxnOrderPay.getTxnDate(), tmTxnOrderPay.getFrontSeqNum());
                        dbsUtil.dbsEndTransaction(false);
                        throw new BizException(RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespCode(), RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespDesc());
                    }

                    returnCode = processRefundRegulation(tmTxnOrderDetList, tmTxnOrderDetListPay);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                        rglog.error("处理退款类交易调账流程失败!所有数据库操作回滚!");
                        dbsUtil.dbsEndTransaction(false);
                        throw new BizException(RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespCode(), RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespDesc());
                    }

                    break;
                default:
                    rglog.error("法人机构<{}>在<{}>的流水号<{}>的原始交易待处理状态不明确,不可调账!", instId, origTransDate, origTraceNo);
                    dbsUtil.dbsEndTransaction(false);
                    throw new BizException(RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespCode(), RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespDesc());
            }

            /* 新增交易流水 */
            tmTxnOrderNew = new TMTxnOrder();
            tmTxnOrderNew.setInstId(txnDataRegulationRequest.getHeader().getInstId());
            tmTxnOrderNew.setTxnDate(txnDataRegulationRequest.getHeader().getTransDate());
            tmTxnOrderNew.setTxnTime(txnDataRegulationRequest.getHeader().getTransTime());
            tmTxnOrderNew.setTxnNum(txnDataRegulationRequest.getHeader().getTxnNum());
            tmTxnOrderNew.setBizType(txnDataRegulationRequest.getHeader().getBizType());
            tmTxnOrderNew.setBizProdCode(tmTxnOrderOld.getBizProdCode());
            tmTxnOrderNew.setMsgSrcId(txnDataRegulationRequest.getHeader().getSrcSysId());
            tmTxnOrderNew.setFrontSeqNum(txnDataRegulationRequest.getHeader().getTraceNo());
            tmTxnOrderNew.setOrderId(txnDataRegulationRequest.getHeader().getTraceNo());
            tmTxnOrderNew.setMchntNo(txnDataRegulationRequest.getHeader().getTraceNo());
            tmTxnOrderNew.setUserId(tmTxnOrderOld.getUserId());
            tmTxnOrderNew.setOrderAmt(tmTxnOrderOld.getOrderAmt());
            tmTxnOrderNew.setTxnAmt(tmTxnOrderOld.getTxnAmt());
            tmTxnOrderNew.setSubsidyAmt(tmTxnOrderOld.getSubsidyAmt());
            tmTxnOrderNew.setBankSubsidyAmt(tmTxnOrderOld.getBankSubsidyAmt());
            tmTxnOrderNew.setMchntSubsidyAmt(tmTxnOrderOld.getMchntSubsidyAmt());
            tmTxnOrderNew.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
            tmTxnOrderNew.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
            tmTxnOrderNew.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
            tmTxnOrderNew.setOrderRemark("{}");
            tmTxnOrderNew.setOrigTxnDate(tmTxnOrderOld.getTxnDate());
            tmTxnOrderNew.setOrigSysSeqNum(tmTxnOrderOld.getFrontSeqNum());
            tmTxnOrderNew.setOrigOrderId(tmTxnOrderOld.getOrderId());
            tmTxnOrderNew.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmTxnOrderNew.setCreateTime(globalTimeStamp);

            /* 统一数据库操作 */
            returnCode = databaseOperation();
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                /* 回滚数据库事务并交易失败 */
                dbsUtil.dbsEndTransaction(false);
                rglog.error("数据库操作失败，回滚所有数据!");

                txnDataRegulationBean.setRegulationStatus(CommonConstant.ONE_COMMON_CONSTANT);
                txnDataRegulationResponse.setOrderDetail(txnDataRegulationBean);

                bizResponse.setRspSysId(ChannelEnum.MOMP.getChannelType());
                bizResponse.setRespCode(RespCodeEnum.SYSTEM_ERROR.getRespCode());
                bizResponse.setRespDesc(RespCodeEnum.SYSTEM_ERROR.getRespDesc());

                txnDataRegulationResponse.setRespCode(RespCodeEnum.SYSTEM_ERROR.getRespCode());
                txnDataRegulationResponse.setRespDesc(RespCodeEnum.SYSTEM_ERROR.getRespDesc());

            } else {
                /* 提交数据库事务并交易成功 */
                dbsUtil.dbsEndTransaction(true);
                rglog.info("数据库操作成功，进行事务提交!");

                txnDataRegulationBean.setRegulationStatus(CommonConstant.ZERO_COMMON_CONSTANT);
                txnDataRegulationResponse.setOrderDetail(txnDataRegulationBean);

                bizResponse.setRspSysId(ChannelEnum.MOMP.getChannelType());
                bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
                bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());

                txnDataRegulationResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
                txnDataRegulationResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());

            }

        } catch (Exception e) {
            dbsUtil.dbsEndTransaction(false);
            rglog.error("出现异常,异常信息:<{}>", StringUtil.ExceptionToString(e));
            throw new BizException(RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespCode(), RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespDesc());
        }

//        dbsUtil.dbsEndTransaction(true);

        bizResponse.setResult(txnDataRegulationResponse);

        return bizResponse;
    }

    /**
     * 初始化应答报文
     * 仅支持将原交易置为失败的操作
     *
     * @param txnDataRegulationRequest TxnDataRegulationRequest
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/6/15 14:43
     */
    private void initResponse(TxnDataRegulationRequest txnDataRegulationRequest, TxnDataRegulationResponse txnDataRegulationResponse) throws Exception {

        globalInstId = txnDataRegulationRequest.getHeader().getInstId();
        globalTraceNo = txnDataRegulationRequest.getHeader().getTraceNo();
        globalTimeStamp = new SimpleDateFormat(CommonConstant.TIMESTAMP_FORMAT).format(new Date());
        globalTxnDate = txnDataRegulationRequest.getHeader().getTransDate();

        /* 初始化调账标志为失败 */
        TxnDataRegulationBean txnDataRegulationBean = txnDataRegulationRequest.getOrderDetail();
        txnDataRegulationBean.setRegulationStatus(CommonConstant.REGULATION_STATUS_FAIL);

        /* 初始化应答报文 */
        txnDataRegulationResponse.setHeader(txnDataRegulationRequest.getHeader());
        txnDataRegulationResponse.setOrderDetail(txnDataRegulationRequest.getOrderDetail());

        /* 判断调账标志,仅支持将原交易置为失败的操作 */
        if (!CommonConstant.REGULATION_STATUS_FAIL.equals(txnDataRegulationBean.getRegulationFlag())) {
            rglog.error("仅可将原交易调为失败状态! REGULATION_FLAG=<{}>", txnDataRegulationBean.getRegulationFlag());
            throw new BizException(RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespCode(), RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespDesc());
        }

        tmTxnOrderOld = null;
        tmTxnOrderPay = null;
        tmTxnOrderNew = null;

        refundType = CommonConstant.REFUND_NON;

        txnFlag = "TXN_FLAG";
        tmTxnOrderDetListNew = new ArrayList<>();
        tmStat2CDayList = new ArrayList<>();
        tmStat2CMchntDayList = new ArrayList<>();
        tmStatMfdDayList = new ArrayList<>();
        tmStatMfdMchntDayList = new ArrayList<>();
        statMfdDayList = new ArrayList<>();
    }

    /**
     * 判断原交易类型及处理流程
     *
     * @param tmTxnOrder 订单流水表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/6/15 14:05
     */
    private void checkOriginalTxnType(TMTxnOrder tmTxnOrder) throws Exception {

        String instId = tmTxnOrder.getInstId();
        String origTransDate = tmTxnOrder.getTxnDate();
        String origTraceNo = tmTxnOrder.getFrontSeqNum();
        String txnNum = tmTxnOrder.getTxnNum();

        if (MompTxnNumEnum.getInstance(txnNum) != null) {
            /* 判断原交易业务流程 */
            switch (MompTxnNumEnum.getInstance(txnNum)) {
                case COMBO_PAYMENT:
                case FEE_DISCOUNT:
                    /* 支付正向交易处理,仅处理该笔交易的流程 */
                    txnFlag = CommonConstant.TXN_FLAG_PAYMENT;
                    break;
                case COMBO_PAYMENT_REFUND:
                case FEE_DISCOUNT_REFUND:
                    /* 支付退货处理,需要同时更新原消费交易状态 */
                    txnFlag = CommonConstant.TXN_FLAG_REFUND;
                    break;
                default:
                    rglog.error("无法判定法人机构<{}>在<{}>的流水号<{}>的原始交易类型!", instId, origTransDate, origTraceNo);
                    throw new BizException(RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespCode(), RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespDesc());
            }
            rglog.info("原始交易类型为<{}>", txnFlag);

        } else {
            rglog.error("无法判定法人机构<{}>在<{}>的流水号<{}>的原始交易类型!", instId, origTransDate, origTraceNo);
            throw new BizException(RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespCode(), RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespDesc());
        }
    }

    /**
     * 支付交易处理流程
     *
     * @param tmTxnOrderDetList 订单明细表
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 14:39
     */
    private int processPaymentRegulation(List<TMTxnOrderDet> tmTxnOrderDetList) throws Exception {

        String instId = tmTxnOrderOld.getInstId();
        String origTransDate = tmTxnOrderOld.getTxnDate();
        String origTraceNo = tmTxnOrderOld.getFrontSeqNum();
        String transStatus = tmTxnOrderOld.getTransStatus();
        String bizStatus = tmTxnOrderOld.getBizStatus();

        /* 判断该笔支付交易是否可以调账 */
        if (!TransStatusEnum.TRANS_SUCC.getStatus().equals(transStatus) && !BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode().equals(bizStatus)) {
            /* 原交易状态异常,不可调账 */
            rglog.error("法人机构<{}>在<{}>的流水号<{}>的交易状态异常,不可调账! TRANS_STATUS=<{}>, BIZ_STATUS=<{}>", instId, origTransDate, origTraceNo, transStatus, bizStatus);
            return CommonConstant.PROCESS_FAILED;
        }

        /* 按交易明细处理额度 */
        for (TMTxnOrderDet tmTxnOrderDet : tmTxnOrderDetList) {

            int returnCode;
            String mcType = tmTxnOrderDet.getMcType().substring(0, 1);

            if (McTypeEnum.MC_TYPE_MO.getMcTypeCode().equals(mcType) || McTypeEnum.MC_TYPE_CP.getMcTypeCode().equals(mcType)) {
                returnCode = processPaymentToClientMcDetail(tmTxnOrderDet);
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    rglog.error("处理对客类明细数据失败!");
                    return returnCode;
                }

            } else if (McTypeEnum.MC_TYPE_MFD.getMcTypeCode().equals(mcType)) {
                returnCode = processPaymentMfdMcDetail(tmTxnOrderDet);
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    rglog.error("处理商户手续费优惠类明细数据失败!");
                    return returnCode;
                }

            } else {
                rglog.error("法人机构<{}>在<{}>的流水号<{}>的原始交易明细等级的营销活动类型异常!MC_TYPE=<{}>", instId, origTransDate, origTraceNo, mcType);
                throw new BizException(RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespCode(), RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespDesc());
            }
        }

        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 退货交易处理流程
     *
     * @param tmTxnOrderDetList    原始退货订单明细
     * @param tmTxnOrderDetListPay 原始支付订单明细
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/6/15 14:39
     */
    private int processRefundRegulation(List<TMTxnOrderDet> tmTxnOrderDetList, List<TMTxnOrderDet> tmTxnOrderDetListPay) throws Exception {

        String instId = tmTxnOrderOld.getInstId();
        String origTransDate = tmTxnOrderOld.getTxnDate();
        String origTraceNo = tmTxnOrderOld.getFrontSeqNum();
        String transStatus = tmTxnOrderOld.getTransStatus();
        String bizStatus = tmTxnOrderOld.getBizStatus();

        /* 按即将调账的退货交易明细处理额度 */
        for (TMTxnOrderDet tmTxnOrderDet : tmTxnOrderDetList) {

            int returnCode;
            String mcType = tmTxnOrderDet.getMcType().substring(0, 1);

            TMTxnOrderDet tmTxnOrderDetPay = tmTxnOrderDetListPay.stream().filter(item -> (item.getMcNo().equals(tmTxnOrderDet.getMcNo()) && item.getMchntNo().equals(tmTxnOrderDet.getMchntNo()))).collect(Collectors.toList()).get(CommonConstant.ZERO);
            if (null == tmTxnOrderDetPay) {
                rglog.error("查找法人机构<{}>在<{}>的流水号<{}>的原消费交易订单明细数据失败!", instId, tmTxnOrderDet.getTxnDate(), tmTxnOrderDet.getFrontSeqNum(), tmTxnOrderDet.getMcNo(), tmTxnOrderDet.getRuleIndex());
                return CommonConstant.PROCESS_FAILED;
            }

            if (McTypeEnum.MC_TYPE_MO.getMcTypeCode().equals(mcType) || McTypeEnum.MC_TYPE_CP.getMcTypeCode().equals(mcType)) {
                returnCode = processRefundToClientMcDetail(tmTxnOrderDet, tmTxnOrderDetPay);
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    rglog.error("处理对客类明细数据失败!");
                    return returnCode;
                }

            } else if (McTypeEnum.MC_TYPE_MFD.getMcTypeCode().equals(mcType)) {
                returnCode = processRefundMfdMcDetail(tmTxnOrderDet, tmTxnOrderDetPay);
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    rglog.error("处理商户手续费优惠类明细数据失败!");
                    return returnCode;
                }

            } else {
                rglog.error("法人机构<{}>在<{}>的流水号<{}>的原始交易明细等级的营销活动类型异常!MC_TYPE=<{}>", instId, origTransDate, origTraceNo, mcType);
                throw new BizException(RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespCode(), RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespDesc());
            }
        }

        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 单笔支付类对客类明细处理
     *
     * @param tmTxnOrderDet 订单明细表
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/6/15 15:10
     */
    private int processPaymentToClientMcDetail(TMTxnOrderDet tmTxnOrderDet) throws Exception {

        int returnCode;
        int updateFlag = CommonConstant.FLAG_NOT_SET;

        String instId = tmTxnOrderDet.getInstId();
        String mcNo = tmTxnOrderDet.getMcNo();
        String traceNo = tmTxnOrderDet.getFrontSeqNum();
        String ruleIndex = tmTxnOrderDet.getRuleIndex();
        String txnDate = globalTxnDate;
        String mchntNo = tmTxnOrderDet.getMchntNo();

        /* 根据营销活动类型取营销活动基本信息,判断是否当前日期还在营销活动有效期内 */
        Object object = selectToClientMcInfo(instId, mcNo);
        if (null == object) {
            rglog.info("未取到营销活动基本信息,无需处理额度相关数据");
            throw new BizException(RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespCode(), RespCodeEnum.TXN_REGULATION_FAILED_ERROR.getRespDesc());
        }

        String mcStartDate;
        String mcEndDate;
        String mcFlag = mcNo.substring(2, 3);

        if (McTypeEnum.MC_TYPE_MO.getMcTypeCode().equals(mcFlag)) {
            /* 减免类营销活动 */
            mcStartDate = ((TMMcMoneyOffInfo) object).getMcStartDate();
            mcEndDate = ((TMMcMoneyOffInfo) object).getMcEndDate();

        } else if (McTypeEnum.MC_TYPE_CP.getMcTypeCode().equals(mcFlag)) {
            /* 卡券类营销活动 */
            mcStartDate = ((TMMcCouponInfo) object).getMcStartDate();
            mcEndDate = ((TMMcCouponInfo) object).getMcEndDate();

        } else {
            rglog.error("未知的营销活动类型,不可调账!");
            return CommonConstant.PROCESS_FAILED;
        }

        /* 判断当前交易日期是否在营销活动有效期内 */
        returnCode = MompDateUtil.checkDateRange(globalTxnDate, mcStartDate, mcEndDate);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.info("当前调账日期<{}>已不在营销活动有效期内<{}>~<{}>,无需调整额度!", globalTxnDate, mcStartDate, mcEndDate);
        } else {

            BigDecimal zero = BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            BigDecimal totalSubsidy = new BigDecimal(tmTxnOrderDet.getSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            BigDecimal bankSubsidy = new BigDecimal(tmTxnOrderDet.getBankSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            BigDecimal mchntSubsidy = new BigDecimal(tmTxnOrderDet.getMchntSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

            String totalSubsidyString = totalSubsidy.multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
            String bankSubsidyString = bankSubsidy.multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
            String mchntSubsidyString = mchntSubsidy.multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();
            BigDecimal orderAmt = new BigDecimal(0).subtract(new BigDecimal(tmTxnOrderOld.getOrderAmt()));

            /* 支付类交易是回退额度,需要做减法,需判断当日可用额度是否足够,不够的话不处理数据 */

            TMStat2CDay tmStat2CDay1 = new TMStat2CDay();
            tmStat2CDay1.setInstId(instId);
            tmStat2CDay1.setTxnDate(globalTxnDate);
            tmStat2CDay1.setMcNo(mcNo);
            tmStat2CDay1.setRuleIndex(ruleIndex);
            tmStat2CDay1.setTotalAmtAcc(totalSubsidyString);
            tmStat2CDay1.setTotalQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);

            if (CommonConstant.ZERO == BigDecimal.ZERO.compareTo(bankSubsidy)) {
                tmStat2CDay1.setBankAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStat2CDay1.setBankQtyAcc(CommonConstant.ZERO_AMOUNT);
            } else {
                tmStat2CDay1.setBankAmtAcc(bankSubsidyString);
                tmStat2CDay1.setBankQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
            }

            if (CommonConstant.ZERO == BigDecimal.ZERO.compareTo(mchntSubsidy)) {
                tmStat2CDay1.setMchntAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStat2CDay1.setMchntQtyAcc(CommonConstant.ZERO_AMOUNT);
            } else {
                tmStat2CDay1.setMchntAmtAcc(mchntSubsidyString);
                tmStat2CDay1.setMchntQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
            }

            tmStat2CDay1.setMchntQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CDay1.setExposureQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CDay1.setExposurePeopleQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CDay1.setAvgTotalAmt(CommonConstant.ZERO_AMOUNT);
            tmStat2CDay1.setAvgBankAmt(CommonConstant.ZERO_AMOUNT);
            tmStat2CDay1.setAvgMchntAmt(CommonConstant.ZERO_AMOUNT);
            tmStat2CDay1.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStat2CDay1.setCreateTime(globalTimeStamp);
            tmStat2CDay1.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStat2CDay1.setUpdateTime(globalTimeStamp);
            tmStat2CDay1.setTxnQtyAcc(orderAmt.toString());
            tmStat2CDayList.add(tmStat2CDay1);

            /* 更新商户维度统计数据 */
            TMStat2CMchntDay tmStat2CMchntDay1 = new TMStat2CMchntDay();
            tmStat2CMchntDay1.setInstId(instId);
            tmStat2CMchntDay1.setTxnDate(globalTxnDate);
            tmStat2CMchntDay1.setMcNo(mcNo);
            tmStat2CMchntDay1.setMchntNo(mchntNo);
            tmStat2CMchntDay1.setTotalAmtAcc(mchntSubsidyString);
            if (mchntSubsidy.compareTo(zero) > CommonConstant.ZERO) {
                tmStat2CMchntDay1.setTotalQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
            } else {
                tmStat2CMchntDay1.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            tmStat2CMchntDay1.setAvgAmtAcc(CommonConstant.ZERO_AMOUNT);
            tmStat2CMchntDay1.setBankAmtAcc(bankSubsidyString);
            if (bankSubsidy.compareTo(zero) > CommonConstant.ZERO) {
                tmStat2CMchntDay1.setBankQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
            } else {
                tmStat2CMchntDay1.setBankQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            tmStat2CMchntDay1.setAvgBankAmtAcc(CommonConstant.ZERO_AMOUNT);
            tmStat2CMchntDay1.setTxnAmtAcc(orderAmt.toString());
            tmStat2CMchntDay1.setExposureQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CMchntDay1.setExposurePeopleQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CMchntDay1.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStat2CMchntDay1.setCreateTime(globalTimeStamp);
            tmStat2CMchntDay1.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStat2CMchntDay1.setUpdateTime(globalTimeStamp);
            tmStat2CMchntDayList.add(tmStat2CMchntDay1);
        }

        /* 判断是否需要更新卡券状态 */
        if (McTypeEnum.MC_TYPE_CP.getMcTypeCode().equals(mcFlag)) {
            /* 将卡券从已核销转换为未核销 */
            returnCode = reverseCouponInfo(tmTxnOrderDet, CouponStatusEnum.NOT_REDEEMED.getCouponStatusCode());
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                rglog.error("回退卡券失败! RETURN_CODE=<{}>", returnCode);
                return CommonConstant.PROCESS_FAILED;
            }
        }

        /* 更新原交易订单明细数据 */
        tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_REGULATED.getBizStatusCode());
        tmTxnOrderDet.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmTxnOrderDet.setUpdateTime(globalTimeStamp);
        TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        returnCode = tmTxnOrderDetMapper.updateSingleOriginalTransactionOrderDetailStatusInfo(tmTxnOrderDet);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("更新法人机构<{}>在<{}>的流水号<{}>的营销活动编号<{}>规则顺序号<{}>的订单明细数据失败! RETURN_CODE=<{}>", instId, txnDate, traceNo, mcNo, ruleIndex, returnCode);
            return CommonConstant.PROCESS_FAILED;
        }

        /* 记录新订单明细数据准备 */
        TMTxnOrderDet tmTxnOrderDet1 = new TMTxnOrderDet();
        tmTxnOrderDet1.setInstId(instId);
        tmTxnOrderDet1.setTxnDate(txnDate);
        tmTxnOrderDet1.setFrontSeqNum(globalTraceNo);
        tmTxnOrderDet1.setOrderId(globalTraceNo);
        tmTxnOrderDet1.setMchntNo(mchntNo);
        tmTxnOrderDet1.setUserId(tmTxnOrderDet.getUserId());
        tmTxnOrderDet1.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
        tmTxnOrderDet1.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
        tmTxnOrderDet1.setMcType(tmTxnOrderDet.getMcType());
        tmTxnOrderDet1.setOriginalAmt(tmTxnOrderDet.getOriginalAmt());
        tmTxnOrderDet1.setMcNo(tmTxnOrderDet.getMcNo());
        tmTxnOrderDet1.setRuleIndex(tmTxnOrderDet.getRuleIndex());
        tmTxnOrderDet1.setSubsidy(tmTxnOrderDet.getSubsidy());
        tmTxnOrderDet1.setBankSubsidy(tmTxnOrderDet.getBankSubsidy());
        tmTxnOrderDet1.setMchntSubsidy(tmTxnOrderDet.getMchntSubsidy());
        tmTxnOrderDet1.setRelativeData(tmTxnOrderDet.getRelativeData());
        tmTxnOrderDet1.setOrderRemark(tmTxnOrderDet.getOrderRemark());
        tmTxnOrderDet1.setOprId(tmTxnOrderDet.getOprId());
        tmTxnOrderDet1.setCreateTime(globalTimeStamp);
        tmTxnOrderDetListNew.add(tmTxnOrderDet1);

        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 单笔退货类对客类明细处理
     *
     * @param tmTxnOrderDet    原始退货订单明细
     * @param tmTxnOrderDetPay 原始支付订单明细
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/6/18 22:57
     */
    private int processRefundToClientMcDetail(TMTxnOrderDet tmTxnOrderDet, TMTxnOrderDet tmTxnOrderDetPay) throws Exception {

        int returnCode;

        String instId = tmTxnOrderDet.getInstId();
        String mcNo = tmTxnOrderDet.getMcNo();
        String traceNo = tmTxnOrderDet.getFrontSeqNum();
        String ruleIndex = tmTxnOrderDet.getRuleIndex();
        String txnDate = globalTxnDate;
        String mchntNo = tmTxnOrderDet.getMchntNo();

        /* 根据营销活动类型取营销活动基本信息,判断是否当前日期还在营销活动有效期内 */
        Object object = selectToClientMcInfo(instId, mcNo);
        if (null == object) {
            rglog.info("未取到营销活动基本信息,无需处理额度相关数据");
        }

        String mcStartDate;
        String mcEndDate;
        String mcFlag = mcNo.substring(2, 3);

        if (McTypeEnum.MC_TYPE_MO.getMcTypeCode().equals(mcFlag) && object != null) {
            /* 减免类营销活动 */
            mcStartDate = ((TMMcMoneyOffInfo) object).getMcStartDate();
            mcEndDate = ((TMMcMoneyOffInfo) object).getMcEndDate();

        } else if (McTypeEnum.MC_TYPE_CP.getMcTypeCode().equals(mcFlag) && object != null) {
            /* 卡券类营销活动 */
            mcStartDate = ((TMMcCouponInfo) object).getMcStartDate();
            mcEndDate = ((TMMcCouponInfo) object).getMcEndDate();

        } else {
            rglog.error("未知的营销活动类型,不可调账!");
            return CommonConstant.PROCESS_FAILED;
        }

        /* 判断当前交易日期是否在营销活动有效期内 */
        returnCode = MompDateUtil.checkDateRange(globalTxnDate, mcStartDate, mcEndDate);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.info("当前调账日期<{}>已不在营销活动有效期内<{}>~<{}>,无需调整额度!", globalTxnDate, mcStartDate, mcEndDate);
        } else {

            BigDecimal zero = BigDecimal.ZERO.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            BigDecimal totalSubsidy = new BigDecimal(tmTxnOrderDet.getSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            BigDecimal bankSubsidy = new BigDecimal(tmTxnOrderDet.getBankSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            BigDecimal mchntSubsidy = new BigDecimal(tmTxnOrderDet.getMchntSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            BigDecimal orderAmt = new BigDecimal(tmTxnOrderOld.getOrderAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

            /* 退货类交易是增加额度,无需其他判断,直接在当日数据基础上加法更新或插入当日数据 */

            TMStat2CDay tmStat2CDay1 = new TMStat2CDay();
            tmStat2CDay1.setInstId(instId);
            tmStat2CDay1.setTxnDate(globalTxnDate);
            tmStat2CDay1.setMcNo(mcNo);
            tmStat2CDay1.setRuleIndex(ruleIndex);
            tmStat2CDay1.setTotalAmtAcc(totalSubsidy.toString());
            tmStat2CDay1.setTotalQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
            if (CommonConstant.ZERO == BigDecimal.ZERO.compareTo(bankSubsidy)) {
                tmStat2CDay1.setBankAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStat2CDay1.setBankQtyAcc(CommonConstant.ZERO_AMOUNT);
            } else {
                tmStat2CDay1.setBankAmtAcc(bankSubsidy.toString());
                tmStat2CDay1.setBankQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
            }
            if (CommonConstant.ZERO == BigDecimal.ZERO.compareTo(mchntSubsidy)) {
                tmStat2CDay1.setMchntAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStat2CDay1.setMchntQtyAcc(CommonConstant.ZERO_AMOUNT);
            } else {
                tmStat2CDay1.setMchntAmtAcc(mchntSubsidy.toString());
                tmStat2CDay1.setMchntQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
            }
            tmStat2CDay1.setMchntQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CDay1.setExposureQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CDay1.setExposurePeopleQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CDay1.setAvgTotalAmt(CommonConstant.ZERO_AMOUNT);
            tmStat2CDay1.setAvgBankAmt(CommonConstant.ZERO_AMOUNT);
            tmStat2CDay1.setAvgMchntAmt(CommonConstant.ZERO_AMOUNT);
            tmStat2CDay1.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStat2CDay1.setCreateTime(globalTimeStamp);
            tmStat2CDay1.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStat2CDay1.setUpdateTime(globalTimeStamp);
            tmStat2CDay1.setTxnQtyAcc(orderAmt.toString());
            tmStat2CDayList.add(tmStat2CDay1);

            /* 更新对客户营销活动商户单日统计表的数据 */
            TMStat2CMchntDay tmStat2CMchntDay1 = new TMStat2CMchntDay();
            tmStat2CMchntDay1.setInstId(instId);
            tmStat2CMchntDay1.setTxnDate(globalTxnDate);
            tmStat2CMchntDay1.setMcNo(mcNo);
            tmStat2CMchntDay1.setMchntNo(mchntNo);
            tmStat2CMchntDay1.setTotalAmtAcc(mchntSubsidy.toString());
            if (mchntSubsidy.compareTo(zero) > CommonConstant.ZERO) {
                tmStat2CMchntDay1.setTotalQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
            } else {
                tmStat2CMchntDay1.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            tmStat2CMchntDay1.setAvgAmtAcc(CommonConstant.ZERO_AMOUNT);
            tmStat2CMchntDay1.setExposureQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStat2CMchntDay1.setExposurePeopleQty(CommonConstant.ZERO_COMMON_CONSTANT);

            tmStat2CMchntDay1.setBankAmtAcc(bankSubsidy.toString());
            if (bankSubsidy.compareTo(zero) > CommonConstant.ZERO) {
                tmStat2CMchntDay1.setBankQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
            } else {
                tmStat2CMchntDay1.setBankQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }

            tmStat2CMchntDay1.setTxnAmtAcc(orderAmt.toString());
            tmStat2CMchntDay1.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStat2CMchntDay1.setCreateTime(globalTimeStamp);
            tmStat2CMchntDay1.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStat2CMchntDay1.setUpdateTime(globalTimeStamp);
            tmStat2CMchntDayList.add(tmStat2CMchntDay1);
        }

        /* 判断是否需要更新卡券状态 */
        if (McTypeEnum.MC_TYPE_CP.getMcTypeCode().equals(mcFlag)) {
            /* 将卡券从已核销转换为未核销 */
            returnCode = reverseCouponInfo(tmTxnOrderDet, CouponStatusEnum.REDEEMED.getCouponStatusCode());
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                rglog.error("回退卡券失败! RETURN_CODE=<{}>", returnCode);
                return CommonConstant.PROCESS_FAILED;
            }
        }

        TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();

        /* 更新原消费交易订单明细数据 */
        tmTxnOrderDetPay.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
        tmTxnOrderDetPay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmTxnOrderDetPay.setUpdateTime(globalTimeStamp);
        returnCode = tmTxnOrderDetMapper.updateSingleOriginalTransactionOrderDetailStatusInfo(tmTxnOrderDetPay);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("更新法人机构<{}>在<{}>的流水号<{}>的营销活动编号<{}>规则顺序号<{}>的原消费交易订单明细数据失败! RETURN_CODE=<{}>", instId, txnDate, traceNo, mcNo, ruleIndex, returnCode);
            return CommonConstant.PROCESS_FAILED;
        }

        /* 更新原退货交易订单明细数据 */
        tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_REGULATED.getBizStatusCode());
        tmTxnOrderDet.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmTxnOrderDet.setUpdateTime(globalTimeStamp);
        returnCode = tmTxnOrderDetMapper.updateSingleOriginalTransactionOrderDetailStatusInfo(tmTxnOrderDet);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("更新法人机构<{}>在<{}>的流水号<{}>的营销活动编号<{}>规则顺序号<{}>的原退货交易订单明细数据失败! RETURN_CODE=<{}>", instId, txnDate, traceNo, mcNo, ruleIndex, returnCode);
            return CommonConstant.PROCESS_FAILED;
        }

        /* 记录新订单明细数据准备 */
        TMTxnOrderDet tmTxnOrderDet1 = new TMTxnOrderDet();
        tmTxnOrderDet1.setInstId(instId);
        tmTxnOrderDet1.setTxnDate(txnDate);
        tmTxnOrderDet1.setFrontSeqNum(globalTraceNo);
        tmTxnOrderDet1.setOrderId(globalTraceNo);
        tmTxnOrderDet1.setMchntNo(mchntNo);
        tmTxnOrderDet1.setUserId(tmTxnOrderDet.getUserId());
        tmTxnOrderDet1.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
        tmTxnOrderDet1.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
        tmTxnOrderDet1.setMcType(tmTxnOrderDet.getMcType());
        tmTxnOrderDet1.setOriginalAmt(tmTxnOrderDet.getOriginalAmt());
        tmTxnOrderDet1.setMcNo(tmTxnOrderDet.getMcNo());
        tmTxnOrderDet1.setRuleIndex(tmTxnOrderDet.getRuleIndex());
        tmTxnOrderDet1.setSubsidy(tmTxnOrderDet.getSubsidy());
        tmTxnOrderDet1.setBankSubsidy(tmTxnOrderDet.getBankSubsidy());
        tmTxnOrderDet1.setMchntSubsidy(tmTxnOrderDet.getMchntSubsidy());
        tmTxnOrderDet1.setRelativeData(tmTxnOrderDet.getRelativeData());
        tmTxnOrderDet1.setOrderRemark(tmTxnOrderDet.getOrderRemark());
        tmTxnOrderDet1.setOprId(tmTxnOrderDet.getOprId());
        tmTxnOrderDet1.setCreateTime(globalTimeStamp);
        tmTxnOrderDetListNew.add(tmTxnOrderDet1);

        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 获取营销活动起始日期和结束日期
     *
     * @param instId 法人机构号
     * @param mcNo   营销活动编号
     * @return java.lang.Object 营销活动基本信息
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/6/17 18:16
     */
    private Object selectToClientMcInfo(String instId, String mcNo) throws Exception {

        String mcType = mcNo.substring(2, 3);
        if (McTypeEnum.MC_TYPE_MO.getMcTypeCode().equals(mcType)) {
            /* 减免类营销活动 */
            McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
            return mcDetailInfoMapper.selectMoneyOffMcDetailInfo(instId, mcNo);

        } else if (McTypeEnum.MC_TYPE_CP.getMcTypeCode().equals(mcType)) {
            /* 卡券类营销活动 */
            TMMcCouponInfo tmMcCouponInfo = new TMMcCouponInfo();
            tmMcCouponInfo.setInstId(instId);
            tmMcCouponInfo.setMcNo(mcNo);

            McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
            return mcDetailInfoMapper.selectCouponMcInfoByPrimaryKey(tmMcCouponInfo);

        } else {
            return null;
        }
    }

    /**
     * 单笔支付类手续费优惠明细处理
     *
     * @param tmTxnOrderDet 订单明细表
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/6/15 15:10
     */
    private int processPaymentMfdMcDetail(TMTxnOrderDet tmTxnOrderDet) throws Exception {

        int returnCode;

        String instId = tmTxnOrderDet.getInstId();
        String mcNo = tmTxnOrderDet.getMcNo();
        String traceNo = tmTxnOrderDet.getFrontSeqNum();
        String ruleIndex = tmTxnOrderDet.getRuleIndex();
        String txnDate = globalTxnDate;
        String mchntNo = tmTxnOrderDet.getMchntNo();

        MchntInfoMapper mchntInfoMapper = new MchntInfoMapperImpl();
        TBMchntBaseInfo mchntBaseInfo = mchntInfoMapper.selectMompMchntBaseInfoByPrimaryKey(instId, mchntNo);
        if (null == mchntBaseInfo) {
            //查询不到商户信息，流程结束
            rglog.error("查询商户基本信息信息失败, INST_ID=<{}>, MCHNT_NO=<{}>", instId, mchntNo);
            throw new BizException(RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespDesc());
        }
        //商户性质
        String mchntType = mchntBaseInfo.getMchntType();
        //独立营销活动标识
        String idpdCmavyFlg = mchntBaseInfo.getMarketFlag();
        //连锁商户号
        String chainMchntNo = mchntBaseInfo.getChainMchntNo();
        //是否独立维护商户资料
        String independentDataFlag = mchntBaseInfo.getIndependentDataFlag();
        if (CommonConstant.YES.equals(independentDataFlag) && MchntTypeEnum.CHAIN_MCHNT_STORE.getMchntType().equals(mchntType) && CommonConstant.ZERO_COMMON_CONSTANT.equals(idpdCmavyFlg)) {
            rglog.info("商户<{}> 商户类型为11:连锁商户门店，商户独立营销活动标识为<{}> 是否独立维护商户资料<{}> 原正向交易计算营销时根据上级商户<{}> 获取营销活动计算的!", mchntNo, idpdCmavyFlg, independentDataFlag, chainMchntNo);
            mchntNo = chainMchntNo;
        } else {
            rglog.info("商户<{}> 是否独立维护商户资料<{}> 商户类型为<{}> 原正向交易无需判断独立营销活动标识，均使用当前商户号计算的营销！", mchntBaseInfo.getMchntNo(), independentDataFlag, idpdCmavyFlg);
        }

        /* 根据营销活动类型取营销活动基本信息,判断是否当前日期还在营销活动有效期内 */
        McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
        TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo = mcDetailInfoMapper.selectMchntFeeDiscountMcDetailInfo(instId, mcNo);
        if (null == tmMcMchntFeeDiscountInfo) {
            rglog.error("获取法人机构<{}>的商户手续费优惠营销活动<{}>信息失败!", instId, mcNo);
            return CommonConstant.PROCESS_FAILED;
        }

        /* 获取消费交易时的统计周期 */
        TMStatMfdCriteriaMapper tmStatMfdCriteriaMapper = new TMStatMfdCriteriaMapperImpl();
        TMStatMfdCriteria tmStatMfdCriteriaOld = tmStatMfdCriteriaMapper.selectTMStatMfdCriteriaByUsingMchntNoAndMcNoAndDateRange(instId, mchntNo, tmTxnOrderDet.getTxnDate(), mcNo);
        if (null == tmStatMfdCriteriaOld) {
            rglog.error("获取法人机构<{}>的商户手续费优惠营销活动<{}>原始消费交易统计周期信息失败!", instId, mcNo, tmTxnOrderDet.getTxnDate());
            return CommonConstant.PROCESS_FAILED;
        }

        /* 获取当前统计周期 */
        TMStatMfdCriteria tmStatMfdCriteriaNew = tmStatMfdCriteriaMapper.selectTMStatMfdCriteriaByUsingMchntNoAndMcNoAndDateRange(instId, mchntNo, txnDate, mcNo);
        if (null != tmStatMfdCriteriaNew) {

            /* 当前调账时间在消费交易的统计周期内,需调整额度 */
            if (tmStatMfdCriteriaOld.getPeriodStartDate().equals(tmStatMfdCriteriaNew.getPeriodStartDate())
                    && tmStatMfdCriteriaOld.getPeriodEndDate().equals(tmStatMfdCriteriaNew.getPeriodEndDate())) {

                BigDecimal totalSubsidy = new BigDecimal(tmTxnOrderDet.getSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                /* 原交易订单明细信息 */
                JsonMfdMcOrderRemark jsonMfdMcOrderRemark = JsonOperation.parseMfdMcOrderDetailOrderRemark(tmTxnOrderDet.getOrderRemark(), rglog);
                if (null == jsonMfdMcOrderRemark) {
                    rglog.error("法人机构<{}>在<{}>的营销活动<{}>的规则<{}>的交易订单明细流水记录<{}>异常,不可调账!", instId, txnDate, mcNo, ruleIndex, tmTxnOrderDet.getOrderRemark());
                    return CommonConstant.PROCESS_FAILED;
                }

                BigDecimal orderAmt = new BigDecimal(jsonMfdMcOrderRemark.getOrderAmt()).multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

                String totalSubsidyString = totalSubsidy.multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString();

                String disTxAmt = tmTxnOrderDet.getDisTxAmt();
                if (null != disTxAmt) {
                    orderAmt = new BigDecimal(disTxAmt).multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
                }

                /* 支付类交易是回退额度,需要做减法,当天无记录则插入，允许单日统计表中存在负值 */
                TMStatMfdDay tmStatMfdDay1 = new TMStatMfdDay();
                tmStatMfdDay1.setInstId(instId);
                tmStatMfdDay1.setTxnDate(txnDate);
                tmStatMfdDay1.setMcNo(mcNo);
                tmStatMfdDay1.setRuleIndex(ruleIndex);
                tmStatMfdDay1.setTotalQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
                tmStatMfdDay1.setTotalAmtAcc(totalSubsidyString);
                tmStatMfdDay1.setTxnQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
                tmStatMfdDay1.setTxnAmtAcc(orderAmt.toString());
                tmStatMfdDay1.setMchntQty(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setMchntOldQualified(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setMchntNewQualified(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setMchntExitQty(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setAvgAmt(CommonConstant.ZERO_AMOUNT);
                tmStatMfdDay1.setPaidAmt(CommonConstant.ZERO_AMOUNT);
                tmStatMfdDay1.setOprId(CommonConstant.DEFAULT_OPR_ID);
                tmStatMfdDay1.setCreateTime(globalTimeStamp);
                tmStatMfdDay1.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
                tmStatMfdDay1.setUpdateTime(globalTimeStamp);
                tmStatMfdDayList.add(tmStatMfdDay1);

                /* 手续费减免活动商户单日统计表 */
                TMStatMfdMchntDay tmStatMfdMchntDay1 = new TMStatMfdMchntDay();
                tmStatMfdMchntDay1.setInstId(instId);
                tmStatMfdMchntDay1.setTxnDate(globalTxnDate);
                tmStatMfdMchntDay1.setMcNo(mcNo);
                tmStatMfdMchntDay1.setMchntNo(mchntNo);
                tmStatMfdMchntDay1.setRuleIndex(ruleIndex);
                tmStatMfdMchntDay1.setTotalQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
                tmStatMfdMchntDay1.setTotalAmtAcc(totalSubsidyString);
                tmStatMfdMchntDay1.setTxnQtyAcc(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
                tmStatMfdMchntDay1.setTxnAmtAcc(orderAmt.toString());
                tmStatMfdMchntDay1.setTotalAvgAmt(CommonConstant.ZERO_AMOUNT);
                tmStatMfdMchntDay1.setExitStatus(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdMchntDay1.setCashbackStatus(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdMchntDay1.setCashbackAmt(CommonConstant.ZERO_AMOUNT);
                tmStatMfdMchntDay1.setOprId(CommonConstant.DEFAULT_OPR_ID);
                tmStatMfdMchntDay1.setCreateTime(globalTimeStamp);
                tmStatMfdMchntDay1.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
                tmStatMfdMchntDay1.setUpdateTime(globalTimeStamp);
                tmStatMfdMchntDayList.add(tmStatMfdMchntDay1);

                String exitDiscountStatus = tmStatMfdCriteriaNew.getExitDiscountStatus();
                String criteriaFlag = tmStatMfdCriteriaNew.getCriteriaFlag();
                //判断是否需要更新达标统计表退出标志
                if (CommonConstant.MC_EXIT_FLAG.equals(exitDiscountStatus) && CommonConstant.CRITERIA_FLAG_SET.equals(criteriaFlag)) {
                    rglog.info("法人机构<{}> 商户手续费优惠营销活动<{}> 商户当前周期已达标，但优惠退出状态为已退出，需要更新退出状态！", instId, mcNo, txnDate);
                    checkExitFlagAndUpdateTMStatMfdCriteria(tmStatMfdCriteriaNew);
                } else {
                }
            } else {
                rglog.info("法人机构<{}> 商户手续费优惠营销活动<{}> 调账时的达标数据统计表周期和原交易的统计周期不同，无需回退统计数据！", instId, mcNo, txnDate);
            }
        } else {
            rglog.info("获取法人机构<{}> 商户手续费优惠营销活动<{}> 调账时的达标数据统计表信息失败，活动可能已结束! 无需回退统计数据！", instId, mcNo, txnDate);
        }
        /* 更新原交易订单明细数据 */
        tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_REGULATED.getBizStatusCode());
        tmTxnOrderDet.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmTxnOrderDet.setUpdateTime(globalTimeStamp);
        TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        returnCode = tmTxnOrderDetMapper.updateSingleOriginalTransactionOrderDetailStatusInfo(tmTxnOrderDet);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("更新法人机构<{}>在<{}>的流水号<{}>的营销活动编号<{}>规则顺序号<{}>的订单明细数据失败! RETURN_CODE=<{}>", instId, txnDate, traceNo, mcNo, ruleIndex, returnCode);
            return CommonConstant.PROCESS_FAILED;
        }

        /* 记录新订单明细数据准备 */
        TMTxnOrderDet tmTxnOrderDet1 = new TMTxnOrderDet();
        tmTxnOrderDet1.setInstId(instId);
        tmTxnOrderDet1.setTxnDate(txnDate);
        tmTxnOrderDet1.setFrontSeqNum(globalTraceNo);
        tmTxnOrderDet1.setOrderId(globalTraceNo);
        tmTxnOrderDet1.setMchntNo(tmTxnOrderDet.getMchntNo());
        tmTxnOrderDet1.setUserId(tmTxnOrderDet.getUserId());
        tmTxnOrderDet1.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
        tmTxnOrderDet1.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
        tmTxnOrderDet1.setMcType(tmTxnOrderDet.getMcType());
        tmTxnOrderDet1.setOriginalAmt(tmTxnOrderDet.getOriginalAmt());
        tmTxnOrderDet1.setMcNo(tmTxnOrderDet.getMcNo());
        tmTxnOrderDet1.setRuleIndex(tmTxnOrderDet.getRuleIndex());
        tmTxnOrderDet1.setSubsidy(tmTxnOrderDet.getSubsidy());
        tmTxnOrderDet1.setBankSubsidy(tmTxnOrderDet.getBankSubsidy());
        tmTxnOrderDet1.setMchntSubsidy(tmTxnOrderDet.getMchntSubsidy());
        tmTxnOrderDet1.setRelativeData(tmTxnOrderDet.getRelativeData());
        tmTxnOrderDet1.setOrderRemark(tmTxnOrderDet.getOrderRemark());
        tmTxnOrderDet1.setOprId(tmTxnOrderDet.getOprId());
        tmTxnOrderDet1.setCreateTime(globalTimeStamp);
        tmTxnOrderDet1.setDisTxAmt(tmTxnOrderDet.getDisTxAmt());
        tmTxnOrderDetListNew.add(tmTxnOrderDet1);

        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * @param tmTxnOrderDet    原始退货订单明细
     * @param tmTxnOrderDetPay 原始支付订单明细
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/6/19 10:09
     */
    private int processRefundMfdMcDetail(TMTxnOrderDet tmTxnOrderDet, TMTxnOrderDet tmTxnOrderDetPay) throws Exception {

        int returnCode;

        String instId = tmTxnOrderDet.getInstId();
        String mcNo = tmTxnOrderDet.getMcNo();
        String traceNo = tmTxnOrderDet.getFrontSeqNum();
        String ruleIndex = tmTxnOrderDet.getRuleIndex();
        String txnDate = globalTxnDate;
        String mchntNo = tmTxnOrderDet.getMchntNo();

        MchntInfoMapper mchntInfoMapper = new MchntInfoMapperImpl();
        TBMchntBaseInfo mchntBaseInfo = mchntInfoMapper.selectMompMchntBaseInfoByPrimaryKey(instId, mchntNo);
        if (null == mchntBaseInfo) {
            //查询不到商户信息，流程结束
            rglog.error("查询商户基本信息信息失败, INST_ID=<{}>, MCHNT_NO=<{}>", instId, mchntNo);
            throw new BizException(RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MCHNT_BASE_INFO_ERROR.getRespDesc());
        }
        //商户性质
        String mchntType = mchntBaseInfo.getMchntType();
        //独立营销活动标识
        String idpdCmavyFlg = mchntBaseInfo.getMarketFlag();
        //连锁商户号
        String chainMchntNo = mchntBaseInfo.getChainMchntNo();
        //是否独立维护商户资料
        String independentDataFlag = mchntBaseInfo.getIndependentDataFlag();
        if (CommonConstant.YES.equals(independentDataFlag) && MchntTypeEnum.CHAIN_MCHNT_STORE.getMchntType().equals(mchntType) && CommonConstant.ZERO_COMMON_CONSTANT.equals(idpdCmavyFlg)) {
            rglog.info("商户<{}> 商户类型为11:连锁商户门店，商户独立营销活动标识为<{}> 是否独立维护商户资料<{}> 原正向交易计算营销时根据上级商户<{}> 获取营销活动计算的!", mchntNo, idpdCmavyFlg, independentDataFlag, chainMchntNo);
            mchntNo = chainMchntNo;
        } else {
            rglog.info("商户<{}> 是否独立维护商户资料<{}> 商户类型为<{}> 原正向交易无需判断独立营销活动标识，均使用当前商户号计算的营销！", mchntBaseInfo.getMchntNo(), independentDataFlag, idpdCmavyFlg);
        }

        /* 取原退货交易订单金额等数据 */
        JsonMfdMcOrderRemark jsonMfdMcOrderRemark = JsonOperation.parseMfdMcOrderDetailOrderRemark(tmTxnOrderDet.getOrderRemark(), rglog);
        if (null == jsonMfdMcOrderRemark) {
            rglog.error("法人机构<{}>在<{}>的营销活动<{}>的规则<{}>的交易订单明细流水记录<{}>异常,不可调账!", instId, txnDate, mcNo, ruleIndex, tmTxnOrderDet.getOrderRemark());
            return CommonConstant.PROCESS_FAILED;
        }
        BigDecimal orderAmt = new BigDecimal(jsonMfdMcOrderRemark.getOrderAmt()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
        /* 退货,需要处理退货统计表数据 */
        TMStatRefundMapper tmStatRefundMapper = new TMStatRefundMapperImpl();
        TMStatRefund tmStatRefund = tmStatRefundMapper.selectSingleRecordFromTMStatRefund(instId, tmTxnOrderDetPay.getTxnDate(), tmTxnOrderDetPay.getFrontSeqNum(), tmTxnOrderDet.getMchntNo());
        if (null == tmStatRefund) {
            rglog.error("获取法人机构<{}>在<{}>的流水号<{}>的营销活动编号<{}>的原消费交易退货统计数据失败!", instId, tmTxnOrderDetPay.getTxnDate(), tmTxnOrderDetPay.getFrontSeqNum(), mcNo);
            return CommonConstant.PROCESS_FAILED;
        }

        /* 无论什么情况都需要更新退货统计表 */
        BigDecimal refundCount = new BigDecimal(tmStatRefund.getRefundCount()).setScale(CommonConstant.DECIMAL_SCALE_ZERO, BigDecimal.ROUND_HALF_UP);
        if (CommonConstant.ZERO == BigDecimal.ONE.compareTo(refundCount)) {
            /* 第一笔退货（或调账已调到还剩一笔退货了）,处理后可认为原消费交易未做过任何退货操作 */
            rglog.info("法人机构<{}>在<{}>的流水号<{}>的营销活动编号<{}>规则顺序号<{}>的原交易已累计退货1次!", instId, txnDate, traceNo, mcNo, ruleIndex);
            refundType = CommonConstant.REFUND_PARTIALLY_FIRST;

            //只有原交易订单是全额退款的时候回退笔数，其他时候不回退，即在全额退款的第一笔调账进行交易笔数的更新
            String biz_status = tmStatRefund.getBizStatus();
            if (BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode().equals(biz_status)) {
                isLastDeal = true;
            } else {
                isLastDeal = false;
            }

            /* 更新退货统计表数据 */
            tmStatRefund.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
            tmStatRefund.setRefundCount(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatRefund.setRefundOrderAmt(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatRefund.setRefundMchntFee(CommonConstant.ZERO_AMOUNT);
            tmStatRefund.setRefundSubsidy(CommonConstant.ZERO_AMOUNT);
            tmStatRefund.setRefundBankSubsidy(CommonConstant.ZERO_AMOUNT);
            tmStatRefund.setRefundMchntSubsidy(CommonConstant.ZERO_AMOUNT);
            tmStatRefund.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatRefund.setUpdateTime(globalTimeStamp);

            returnCode = tmStatRefundMapper.updateSingleRecordFromTmStatRefundDirectly(tmStatRefund);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                rglog.error("更新法人机构<{}>在<{}>的流水号<{}>的营销活动编号<{}>规则顺序号<{}>的退货统计数据失败! RETURN_CODE=<{}>", instId, txnDate, traceNo, mcNo, ruleIndex, returnCode);
                return CommonConstant.PROCESS_FAILED;
            }

            /* 更新原消费交易订单明细数数据 */
            tmTxnOrderDetPay.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());

        } else {
            /* 第n笔退货,处理后认为原交易依然是部分退货状态 */

            refundType = CommonConstant.REFUND_PARTIALLY;

            //只有原交易订单是全额退款的时候回退笔数，其他时候不回退，即在全额退款的第一笔调账进行交易笔数的更新
            String biz_status = tmStatRefund.getBizStatus();
            if (BizStatusEnum.PROCESS_REFUNDED.getBizStatusCode().equals(biz_status)) {
                isLastDeal = true;
            } else {
                isLastDeal = false;
            }

            /* 更新退货统计表数据 */
            BigDecimal MINUS_ONE = new BigDecimal(CommonConstant.MINUS_ONE).setScale(CommonConstant.DECIMAL_SCALE_ZERO, RoundingMode.HALF_UP);
            BigDecimal mchntFeeReceivable = new BigDecimal(tmTxnOrderDet.getOriginalAmt());
            BigDecimal mchntFeeDiscount = new BigDecimal(tmTxnOrderDet.getSubsidy());
            BigDecimal mchntFeeActual = mchntFeeReceivable.subtract(mchntFeeDiscount);
            mchntFeeReceivable = mchntFeeReceivable.multiply(MINUS_ONE).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            mchntFeeDiscount = mchntFeeDiscount.multiply(MINUS_ONE).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            mchntFeeActual = mchntFeeActual.multiply(MINUS_ONE).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            BigDecimal bankSubsidy = new BigDecimal(tmTxnOrderDet.getBankSubsidy()).multiply(MINUS_ONE).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            BigDecimal mchntSubsidy = new BigDecimal(tmTxnOrderDet.getMchntSubsidy()).multiply(MINUS_ONE).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

            tmStatRefund.setBizStatus(BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode());
            tmStatRefund.setRefundCount(CommonConstant.MINUS_ONE_COMMON_CONSTANT);
            tmStatRefund.setRefundOrderAmt(orderAmt.multiply(new BigDecimal(CommonConstant.MINUS_ONE).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP)).toString());
            tmStatRefund.setMchntFee(mchntFeeReceivable.toString());
            tmStatRefund.setRefundSubsidy(mchntFeeDiscount.toString());
            tmStatRefund.setRefundMchntFee(mchntFeeActual.toString());
            tmStatRefund.setRefundBankSubsidy(bankSubsidy.toString());
            tmStatRefund.setRefundMchntSubsidy(mchntSubsidy.toString());
            tmStatRefund.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatRefund.setUpdateTime(globalTimeStamp);

            returnCode = tmStatRefundMapper.updateSingleRecordFromTmStatRefund(tmStatRefund);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                rglog.error("更新法人机构<{}>在<{}>的流水号<{}>的营销活动编号<{}>规则顺序号<{}>的退货统计数据失败! RETURN_CODE=<{}>", instId, txnDate, traceNo, mcNo, ruleIndex, returnCode);
                return CommonConstant.PROCESS_FAILED;
            }

            tmTxnOrderDetPay.setBizStatus(BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode());
        }

        /* 根据营销活动类型取营销活动基本信息,判断是否当前日期还在营销活动有效期内 */
        McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
        TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo = mcDetailInfoMapper.selectMchntFeeDiscountMcDetailInfo(instId, mcNo);
        if (null == tmMcMchntFeeDiscountInfo) {
            rglog.error("获取法人机构<{}>的商户手续费优惠营销活动<{}>信息失败!", instId, mcNo);
            return CommonConstant.PROCESS_FAILED;
        }

        /* 获取消费交易时的统计周期 */
        TMStatMfdCriteriaMapper tmStatMfdCriteriaMapper = new TMStatMfdCriteriaMapperImpl();
        TMStatMfdCriteria tmStatMfdCriteriaOld = tmStatMfdCriteriaMapper.selectTMStatMfdCriteriaByUsingMchntNoAndMcNoAndDateRange(instId, mchntNo, tmTxnOrderPay.getTxnDate(), mcNo);
        if (null == tmStatMfdCriteriaOld) {
            rglog.error("获取法人机构<{}>的商户手续费优惠营销活动<{}>原始消费交易统计周期信息失败!", instId, mcNo, tmTxnOrderDet.getTxnDate());
            return CommonConstant.PROCESS_FAILED;
        }

        /* 获取当前统计周期 */
        TMStatMfdCriteria tmStatMfdCriteriaNew = tmStatMfdCriteriaMapper.selectTMStatMfdCriteriaByUsingMchntNoAndMcNoAndDateRange(instId, mchntNo, txnDate, mcNo);
        if (null == tmStatMfdCriteriaNew) {
            rglog.error("获取法人机构<{}>的商户手续费优惠营销活动<{}>调账交易统计周期信息失败!", instId, mcNo, txnDate);
            return CommonConstant.PROCESS_FAILED;
        }

        String disTxAmt = tmTxnOrderDet.getDisTxAmt();
        if (null != disTxAmt) {
            orderAmt = new BigDecimal(disTxAmt).multiply(new BigDecimal(CommonConstant.MINUS_ONE)).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        }

        /* 当前调账时间在消费交易的统计周期内,需调整额度 */
        if (tmStatMfdCriteriaOld.getPeriodStartDate().equals(tmStatMfdCriteriaNew.getPeriodStartDate()) && tmStatMfdCriteriaOld.getPeriodEndDate().equals(tmStatMfdCriteriaNew.getPeriodEndDate())) {

            /* 退货类交易是增加额度,无需其他判断,直接在当日数据基础上加法更新或插入当日数据 */

            BigDecimal totalSubsidy = new BigDecimal(tmTxnOrderDet.getSubsidy()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            String totalSubsidyString = totalSubsidy.toString();

            /* 手续费减免活动单日统计表 */
            TMStatMfdDay tmStatMfdDay1 = new TMStatMfdDay();
            tmStatMfdDay1.setInstId(instId);
            tmStatMfdDay1.setTxnDate(txnDate);
            tmStatMfdDay1.setMcNo(mcNo);
            tmStatMfdDay1.setRuleIndex(ruleIndex);

            //如果退货调账后，订单没有退货记录了，则需要更新统计表中的笔数汇总
            if (isLastDeal) {
                tmStatMfdDay1.setTotalQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
                tmStatMfdDay1.setTxnQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
            } else {
                tmStatMfdDay1.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            tmStatMfdDay1.setTotalAmtAcc(totalSubsidyString);
            tmStatMfdDay1.setTxnAmtAcc(orderAmt.toString());
            tmStatMfdDay1.setMchntQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay1.setMchntOldQualified(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay1.setMchntNewQualified(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay1.setMchntExitQty(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay1.setAvgAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdDay1.setPaidAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdDay1.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdDay1.setCreateTime(globalTimeStamp);
            tmStatMfdDay1.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdDay1.setUpdateTime(globalTimeStamp);
            tmStatMfdDayList.add(tmStatMfdDay1);

            /* 手续费减免活动商户单日统计表 */
            TMStatMfdMchntDay tmStatMfdMchntDay1 = new TMStatMfdMchntDay();
            tmStatMfdMchntDay1.setInstId(instId);
            tmStatMfdMchntDay1.setTxnDate(globalTxnDate);
            tmStatMfdMchntDay1.setMcNo(mcNo);
            tmStatMfdMchntDay1.setMchntNo(mchntNo);
            tmStatMfdMchntDay1.setRuleIndex(ruleIndex);
            //如果退货调账后，订单没有退货记录了，则需要更新统计表中的笔数汇总
            if (isLastDeal) {
                tmStatMfdMchntDay1.setTotalQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
                tmStatMfdMchntDay1.setTxnQtyAcc(CommonConstant.ONE_COMMON_CONSTANT);
            } else {
                tmStatMfdMchntDay1.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdMchntDay1.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            tmStatMfdMchntDay1.setTotalAmtAcc(totalSubsidyString);
            tmStatMfdMchntDay1.setTxnAmtAcc(orderAmt.toString());
            tmStatMfdMchntDay1.setTotalAvgAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdMchntDay1.setExitStatus(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay1.setCashbackStatus(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay1.setCashbackAmt(CommonConstant.ZERO_AMOUNT);
            tmStatMfdMchntDay1.setOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdMchntDay1.setCreateTime(globalTimeStamp);
            tmStatMfdMchntDay1.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmStatMfdMchntDay1.setUpdateTime(globalTimeStamp);
            tmStatMfdMchntDayList.add(tmStatMfdMchntDay1);
        }

        /* 更新原消费交易订单明细数数据 */
        tmTxnOrderDetPay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmTxnOrderDetPay.setUpdateTime(globalTimeStamp);
        returnCode = tmTxnOrderDetMapper.updateSingleOriginalTransactionOrderDetailStatusInfo(tmTxnOrderDetPay);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("更新法人机构<{}>在<{}>的流水号<{}>的营销活动编号<{}>规则顺序号<{}>的原消费交易订单明细数据失败! RETURN_CODE=<{}>", instId, txnDate, traceNo, mcNo, ruleIndex, returnCode);
            return CommonConstant.PROCESS_FAILED;
        }

        /* 更新原退货交易订单明细数据 */
        tmTxnOrderDet.setBizStatus(BizStatusEnum.PROCESS_REGULATED.getBizStatusCode());
        tmTxnOrderDet.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmTxnOrderDet.setUpdateTime(globalTimeStamp);
        returnCode = tmTxnOrderDetMapper.updateSingleOriginalTransactionOrderDetailStatusInfo(tmTxnOrderDet);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("更新法人机构<{}>在<{}>的流水号<{}>的营销活动编号<{}>规则顺序号<{}>的原退货交易订单明细数据失败! RETURN_CODE=<{}>", instId, txnDate, traceNo, mcNo, ruleIndex, returnCode);
            return CommonConstant.PROCESS_FAILED;
        }

        /* 记录新订单明细数据准备 */
        TMTxnOrderDet tmTxnOrderDet1 = new TMTxnOrderDet();
        tmTxnOrderDet1.setInstId(instId);
        tmTxnOrderDet1.setTxnDate(txnDate);
        tmTxnOrderDet1.setFrontSeqNum(globalTraceNo);
        tmTxnOrderDet1.setOrderId(globalTraceNo);
        tmTxnOrderDet1.setMchntNo(tmTxnOrderDet.getMchntNo());
        tmTxnOrderDet1.setUserId(tmTxnOrderDet.getUserId());
        tmTxnOrderDet1.setVerifyStatus(CommonConstant.VERIFY_STATUS_INIT);
        tmTxnOrderDet1.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
        tmTxnOrderDet1.setMcType(tmTxnOrderDet.getMcType());
        tmTxnOrderDet1.setOriginalAmt(tmTxnOrderDet.getOriginalAmt());
        tmTxnOrderDet1.setMcNo(tmTxnOrderDet.getMcNo());
        tmTxnOrderDet1.setRuleIndex(tmTxnOrderDet.getRuleIndex());
        tmTxnOrderDet1.setSubsidy(tmTxnOrderDet.getSubsidy());
        tmTxnOrderDet1.setBankSubsidy(tmTxnOrderDet.getBankSubsidy());
        tmTxnOrderDet1.setMchntSubsidy(tmTxnOrderDet.getMchntSubsidy());
        tmTxnOrderDet1.setRelativeData(tmTxnOrderDet.getRelativeData());
        tmTxnOrderDet1.setOrderRemark(tmTxnOrderDet.getOrderRemark());
        tmTxnOrderDet1.setOprId(tmTxnOrderDet.getOprId());
        tmTxnOrderDet1.setCreateTime(globalTimeStamp);
        tmTxnOrderDet1.setDisTxAmt(tmTxnOrderDet.getDisTxAmt());
        tmTxnOrderDetListNew.add(tmTxnOrderDet1);

        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 处理卡券信息
     *
     * @param tmTxnOrderDet 订单明细表
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/23 18:24
     */
    private int reverseCouponInfo(TMTxnOrderDet tmTxnOrderDet, String couponStatus) throws Exception {

        /* 更新卡券信息表 */
        TMCouponInfo tmCouponInfo = new TMCouponInfo();
        tmCouponInfo.setInstId(tmTxnOrderDet.getInstId());
        tmCouponInfo.setCouponStatus(couponStatus);
        tmCouponInfo.setOrderId("");
        tmCouponInfo.setRedeemTime("");

        JSONObject relativeDataJson = JSONObject.parseObject(tmTxnOrderDet.getRelativeData());
        //原商户订单明细金额
        String couponNo = relativeDataJson.get("couponNo").toString();
        tmCouponInfo.setCouponNo(couponNo);

        CouponInfoMapper couponInfoMapper = new CouponInfoMapperImpl();
        int returnCode = couponInfoMapper.reverseRedeemedCoupon(tmCouponInfo);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            rglog.error("退回卡券<{}>失败!", tmCouponInfo.getCouponNo());
            return CommonConstant.PROCESS_FAILED;
        } else {
            rglog.info("退回卡券<{}>成功!", tmCouponInfo.getCouponNo());
            return CommonConstant.PROCESS_SUCCESS;
        }
    }

    /**
     * 数据库统一操作
     * 返回0表示成功
     * 返回-1表示失败
     *
     * @return int 返回码
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/6/18 09:45
     */
    private int databaseOperation() throws Exception {

        int returnCode;

        /* 更新对客类额度 */
        if (!tmStat2CDayList.isEmpty()) {

            TMStat2CDayMapper tmStat2CDayMapper = new TMStat2CDayMapperImpl();
            for (TMStat2CDay tmStat2CDay : tmStat2CDayList) {

                /* 先更新数据,更新失败再插入数据 */
                returnCode = tmStat2CDayMapper.updateToClientMcDayStatistics(tmStat2CDay);
                if (Database.DBS_NOT_FOUND == returnCode) {
                    /* 插入数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex(), returnCode);
                    returnCode = tmStat2CDayMapper.insertSingleToClientMcDayStatistics(tmStat2CDay);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                        /* 更新失败 */
                        rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex(), returnCode);
                        return CommonConstant.PROCESS_FAILED;
                    }
                    rglog.info("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据成功", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex());
                } else if (Database.DBS_SUCCESS != returnCode) {
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex(), returnCode);
                    return CommonConstant.PROCESS_FAILED;
                } else {
                    rglog.info("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据成功", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex());
                }

                /* 先更新数据,更新失败再插入数据  规则为0的*/
                tmStat2CDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);
                returnCode = tmStat2CDayMapper.updateToClientMcDayStatistics(tmStat2CDay);
                if (Database.DBS_NOT_FOUND == returnCode) {
                    /* 插入数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex(), returnCode);
                    returnCode = tmStat2CDayMapper.insertSingleToClientMcDayStatistics(tmStat2CDay);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                        /* 更新失败 */
                        rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex(), returnCode);
                        return CommonConstant.PROCESS_FAILED;
                    }
                    rglog.info("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据成功", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex());
                } else if (Database.DBS_SUCCESS != returnCode) {
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex(), returnCode);
                    return CommonConstant.PROCESS_FAILED;
                } else {
                    rglog.info("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据成功", tmStat2CDay.getInstId(), tmStat2CDay.getMcNo(), tmStat2CDay.getRuleIndex());
                }
            }
        }

        if (!tmStat2CMchntDayList.isEmpty()) {
            TMStat2CMchntDayMapper tmStat2CMchntDayMapper = new TMStat2CMchntDayMapperImpl();
            for (TMStat2CMchntDay tmStat2CMchntDay : tmStat2CMchntDayList) {

                /* 先更新数据,更新失败再插入数据 */
                returnCode = tmStat2CMchntDayMapper.updateToClientMcMchntDayStatistics(tmStat2CMchntDay);
                if (Database.DBS_NOT_FOUND == returnCode) {
                    /* 插入数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的商户<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStat2CMchntDay.getInstId(), tmStat2CMchntDay.getMcNo(), tmStat2CMchntDay.getMchntNo(), returnCode);
                    returnCode = tmStat2CMchntDayMapper.insertSingleToClientMcMchntDayStatistics(tmStat2CMchntDay);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                        /* 更新失败 */
                        rglog.error("插入法人机构<{}>的营销活动<{}>的商户<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStat2CMchntDay.getInstId(), tmStat2CMchntDay.getMcNo(), tmStat2CMchntDay.getMchntNo(), returnCode);
                        return CommonConstant.PROCESS_FAILED;
                    }
                    rglog.info("插入法人机构<{}>的营销活动<{}>的商户<{}>的单日统计数据成功", tmStat2CMchntDay.getInstId(), tmStat2CMchntDay.getMcNo(), tmStat2CMchntDay.getMchntNo());
                } else if (Database.DBS_SUCCESS != returnCode) {
                    rglog.error("更新法人机构<{}>的营销活动<{}>的商户<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStat2CMchntDay.getInstId(), tmStat2CMchntDay.getMcNo(), tmStat2CMchntDay.getMchntNo(), returnCode);
                    return CommonConstant.PROCESS_FAILED;
                } else {
                    rglog.info("更新法人机构<{}>的营销活动<{}>的商户<{}>的单日统计数据成功", tmStat2CMchntDay.getInstId(), tmStat2CMchntDay.getMcNo(), tmStat2CMchntDay.getMchntNo());
                }
            }
        }

        /* 更新手续费优惠类额度 */
        if (!tmStatMfdDayList.isEmpty()) {
            /* 手续费减免活动单日统计表 */
            TMStatMfdDayMapper tmStatMfdDayMapper = new TMStatMfdDayMapperImpl();
            for (TMStatMfdDay tmStatMfdDay : tmStatMfdDayList) {

                /* 先更新数据,更新失败再插入数据 */
                returnCode = tmStatMfdDayMapper.updateMchntFeeDiscountDayStatistics(tmStatMfdDay);
                if (Database.DBS_NOT_FOUND == returnCode) {
                    /* 插入数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                    returnCode = tmStatMfdDayMapper.insertMchntFeeDiscountDayStatistics(tmStatMfdDay);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                        /* 更新失败 */
                        rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                        return CommonConstant.PROCESS_FAILED;
                    }
                    rglog.info("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据成功", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex());
                } else if (Database.DBS_SUCCESS != returnCode) {
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                    return CommonConstant.PROCESS_FAILED;
                } else {
                    rglog.info("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据成功", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex());
                }

                //如果当前规则不是0 ，则还需要更新规则为0的记录
                if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdDay.getRuleIndex())) {
                    tmStatMfdDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);
                    returnCode = tmStatMfdDayMapper.updateMchntFeeDiscountDayStatistics(tmStatMfdDay);
                    if (Database.DBS_NOT_FOUND == returnCode) {
                        /* 插入数据失败 */
                        rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                        returnCode = tmStatMfdDayMapper.insertMchntFeeDiscountDayStatistics(tmStatMfdDay);
                        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                            /* 更新失败 */
                            rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                            return CommonConstant.PROCESS_FAILED;
                        }
                        rglog.info("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据成功", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex());
                    } else if (Database.DBS_SUCCESS != returnCode) {
                        rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex(), returnCode);
                        return CommonConstant.PROCESS_FAILED;
                    } else {
                        rglog.info("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据成功", tmStatMfdDay.getInstId(), tmStatMfdDay.getMcNo(), tmStatMfdDay.getRuleIndex());
                    }
                }
            }
        }

        if (!tmStatMfdMchntDayList.isEmpty()) {
            /* 手续费减免活动商户单日统计表 */
            TMStatMfdMchntDayMapper tmStatMfdMchntDayMapper = new TMStatMfdMchntDayMapperImpl();

            for (TMStatMfdMchntDay tmStatMfdMchntDay : tmStatMfdMchntDayList) {

                /* 先更新数据,更新失败再插入数据 */
                returnCode = tmStatMfdMchntDayMapper.updateMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
                if (Database.DBS_NOT_FOUND == returnCode) {
                    /* 插入数据失败 */
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                    returnCode = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
                    if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                        /* 更新失败 */
                        rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                        return CommonConstant.PROCESS_FAILED;
                    }
                    rglog.info("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据成功", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex());
                } else if (Database.DBS_SUCCESS != returnCode) {
                    rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                    return CommonConstant.PROCESS_FAILED;
                } else {
                    rglog.info("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据成功", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex());
                }

                //如果当前规则不是0 ，则还需要更新规则为0的记录
                if (!CommonConstant.ZERO_COMMON_CONSTANT.equals(tmStatMfdMchntDay.getRuleIndex())) {
                    tmStatMfdMchntDay.setRuleIndex(CommonConstant.ZERO_COMMON_CONSTANT);
                    returnCode = tmStatMfdMchntDayMapper.updateMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
                    if (Database.DBS_NOT_FOUND == returnCode) {
                        /* 插入数据失败 */
                        rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                        returnCode = tmStatMfdMchntDayMapper.insertMchntFeeDiscountMchntDayStatistics(tmStatMfdMchntDay);
                        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                            /* 更新失败 */
                            rglog.error("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                            return CommonConstant.PROCESS_FAILED;
                        }
                        rglog.info("插入法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据成功", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex());
                    } else if (Database.DBS_SUCCESS != returnCode) {
                        rglog.error("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据失败! RETURN_CODE=<{}>", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex(), returnCode);
                        return CommonConstant.PROCESS_FAILED;
                    } else {
                        rglog.info("更新法人机构<{}>的营销活动<{}>的规则<{}>的单日统计数据成功", tmStatMfdMchntDay.getInstId(), tmStatMfdMchntDay.getMcNo(), tmStatMfdMchntDay.getRuleIndex());
                    }
                }
            }
        }

        /* 登记调账交易订单明细 */
        if (!tmTxnOrderDetListNew.isEmpty()) {

            TMTxnOrderDetMapper tmTxnOrderDetMapper = new TMTxnOrderDetMapperImpl();
            for (TMTxnOrderDet tmTxnOrderDet : tmTxnOrderDetListNew) {

                /* 插入数据 */
                returnCode = tmTxnOrderDetMapper.insertSingleRecordIntoTMTxnOrderDet(tmTxnOrderDet);
                if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                    /* 更新失败 */
                    rglog.error("插入法人机构<{}>的营销活动<{}>的商户<{}>的订单明细数据失败! RETURN_CODE=<{}>", tmTxnOrderDet.getInstId(), tmTxnOrderDet.getMcNo(), tmTxnOrderDet.getMchntNo(), returnCode);
                    return CommonConstant.PROCESS_FAILED;
                }
                rglog.info("插入法人机构<{}>的营销活动<{}>的商户<{}>的订单明细数据成功", tmTxnOrderDet.getInstId(), tmTxnOrderDet.getMcNo(), tmTxnOrderDet.getMchntNo());
            }
        }


        TMTxnOrderMapper tmTxnOrderMapper = new TMTxnOrderMapperImpl();

        /* 处理原支付交易订单流水记录 */
        if (CommonConstant.REFUND_NON == refundType) {
            /* 调消费交易,无需处理 */
            rglog.info("本次调账流程处理的是支付类交易,无需调账支付类交易的原交易信息!");
        } else {

            if (CommonConstant.REFUND_FULLY == refundType || CommonConstant.REFUND_PARTIALLY_FIRST == refundType) {
                /* 调第一次退货或全额退货,调整完毕后原消费流水应为成功状态 */
                tmTxnOrderPay.setBizStatus(BizStatusEnum.PROCESS_SUCCESS.getBizStatusCode());
            } else {
                /* 部分退货非第一笔的场景,调整完毕后原消费流水应为已部分退货状态 */
                tmTxnOrderPay.setBizStatus(BizStatusEnum.PROCESS_PARTIALLY_REFUNDED.getBizStatusCode());
            }

            tmTxnOrderPay.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
            tmTxnOrderPay.setUpdateTime(globalTimeStamp);
            returnCode = tmTxnOrderMapper.updateOriginalTransactionOrderBizStatus(tmTxnOrderPay);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                /* 更新失败 */
                rglog.error("更新法人机构<{}>的流水号<{}>的订单号<{}>的原交易状态成功! RETURN_CODE=<{}>", tmTxnOrderPay.getInstId(), tmTxnOrderPay.getFrontSeqNum(), tmTxnOrderPay.getOrderId(), returnCode);
                return CommonConstant.PROCESS_FAILED;
            }
            rglog.info("更新法人机构<{}>的流水号<{}>的订单号<{}>的原交易状态成功!", tmTxnOrderPay.getInstId(), tmTxnOrderPay.getFrontSeqNum(), tmTxnOrderPay.getOrderId());
        }

        /* 处理待调账交易订单流水记录 */
        tmTxnOrderOld.setBizStatus(BizStatusEnum.PROCESS_REGULATED.getBizStatusCode());
        tmTxnOrderOld.setLastOprId(CommonConstant.DEFAULT_OPR_ID);
        tmTxnOrderOld.setUpdateTime(globalTimeStamp);
        returnCode = tmTxnOrderMapper.updateOriginalTransactionOrderBizStatus(tmTxnOrderOld);
        if (CommonConstant.PROCESS_SUCCESS != returnCode) {
            /* 更新失败 */
            rglog.error("更新法人机构<{}>的流水号<{}>的订单号<{}>的原交易状态成功! RETURN_CODE=<{}>", tmTxnOrderNew.getInstId(), tmTxnOrderNew.getFrontSeqNum(), tmTxnOrderNew.getOrderId(), returnCode);
            return CommonConstant.PROCESS_FAILED;
        }
        rglog.info("更新法人机构<{}>的流水号<{}>的订单号<{}>的原交易状态成功!", tmTxnOrderNew.getInstId(), tmTxnOrderNew.getFrontSeqNum(), tmTxnOrderNew.getOrderId());

        /* 登记调账交易订单流水记录 */
        if (null != tmTxnOrderNew) {
            /* 登记订单流水 */
            returnCode = tmTxnOrderMapper.insertSingleRecordIntoTMTxnOrder(tmTxnOrderNew);
            if (CommonConstant.PROCESS_SUCCESS != returnCode) {
                /* 更新失败 */
                rglog.error("插入法人机构<{}>的流水号<{}>的订单号<{}>的订单数据失败! RETURN_CODE=<{}>", tmTxnOrderNew.getInstId(), tmTxnOrderNew.getFrontSeqNum(), tmTxnOrderNew.getOrderId(), returnCode);
                return CommonConstant.PROCESS_FAILED;
            }
            rglog.info("插入法人机构<{}>的流水号<{}>的订单号<{}>的订单数据成功!", tmTxnOrderNew.getInstId(), tmTxnOrderNew.getFrontSeqNum(), tmTxnOrderNew.getOrderId());
        }

        return CommonConstant.PROCESS_SUCCESS;
    }

    /**
     * 判断规则限制是否达到上限
     *
     * @author liujinan
     * @date 2020/9/23 17:27
     */
    private Boolean judgeIsReachRuleOrMchntLimit(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, TMStatMfdCriteria tmStatMfdCriteria) throws Exception {

        String instId = tmStatMfdCriteria.getInstId();
        String mcNo = tmStatMfdCriteria.getMcNo();
        String mchntNo = tmStatMfdCriteria.getMchntNo();

        //各维度目前的统计值
        //手续费减免活动商户统计 具体规则-累计优惠金额
        BigDecimal totalAmtAcc = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTotalAmtAcc());
        //手续费减免活动商户单日统计数据 具体规则-累计优惠金额
        BigDecimal totalAmtAccDay = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTotalAmtAcc());
        //规则维度判断是否达到上限使用
        BigDecimal alredayUseedtotalAmtAccRule = totalAmtAcc.add(totalAmtAccDay);

        rglog.info("机构<{}>营销活动<{}> 规则<{}> 商户<{}> 开始进行规则层面额度是否达到上限判断...", instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mchntNo);
        //获取当前规则的上限值
        String ruleLimit;
        if (null != tmStatMfdCriteria.getMrctDisUpLmtVal() && !"".equals(tmStatMfdCriteria.getMrctDisUpLmtVal())) {
            rglog.info("营销活动<{}> 商户<{}> 达标统计表 商户优惠上限值 字段有值，直接使用字段值<{}> 作为上限，无需通过计算规则重新计算!", mcNo, mchntNo, mcMchntFeeDiscountTransData.getMrctDisUpLmtVal());
            ruleLimit = tmStatMfdCriteria.getMrctDisUpLmtVal();
        } else {
            /* 根据营销活动规则计算商户当前优惠限额 */
            if (FeeCalTypeEnum.TYPE_0.getRuleType().equals(mcMchntFeeDiscountTransData.getCalRuleNo())) {
                /* 无上限，肯定没有达到额度*/
                rglog.info("机构<{}>营销活动<{}> 规则<{}>的计算规则<{}> 规则设置无优惠上限！",
                        instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mcMchntFeeDiscountTransData.getCalRuleNo());
                ruleLimit = CommonConstant.BIG_NUMBER;
            } else if (FeeCalTypeEnum.TYPE_1.getRuleType().equals(mcMchntFeeDiscountTransData.getCalRuleNo())) {
                /* 无需取优惠限额的计算规则,直接使用规则中的限额 */
                ruleLimit = mcMchntFeeDiscountTransData.getDiscountLimit();
                rglog.info("机构<{}>营销活动<{}> 规则<{}>的计算规则<{}> 规则设置指定具体金额<{}>！",
                        instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mcMchntFeeDiscountTransData.getCalRuleNo(), ruleLimit);
            } else {
                TMPlatCalRule tmPlatCalRule = selectCalculationRuleInfoByPK(instId, mcMchntFeeDiscountTransData.getCalRuleNo());
                if (null == tmPlatCalRule) {
                    /* 未取到营销活动规则信息,本营销活动不可以优惠! */
                    rglog.info("获取机构<{}>的营销活动<{}>的优惠规则<{}>的计算规则<{}>信息匹配,本营销活动不予优惠!",
                            instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mcMchntFeeDiscountTransData.getCalRuleNo());
                    throw new BizException(RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespDesc());
                }
                //根据规则计算限额值
                ruleLimit = calculateMchntFeeDiscountLimit(instId, mchntNo, tmPlatCalRule.getRuleType(), tmStatMfdCriteria.getCriteriaValue());
                rglog.info("机构<{}>营销活动<{}> 规则<{}>的计算规则<{}> 规则设置上限计算方式<{}>，计算出的值为<{}>！",
                        instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mcMchntFeeDiscountTransData.getCalRuleNo(), tmPlatCalRule.getRuleType(), ruleLimit);
            }
        }
        if (alredayUseedtotalAmtAccRule.compareTo(new BigDecimal(ruleLimit)) >= CommonConstant.ZERO) {
            rglog.info("机构<{}>营销活动<{}> 规则<{}> ，优惠限额<{}> 规则层面已累计使用额度<{}> 规则层面已达到限额，调账不再回退额度",
                    instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), ruleLimit, alredayUseedtotalAmtAccRule);
            return false;
        }

        /* 判断单个商户营销活动优惠退出条件 */
        String terminationFlag = mcMchntFeeDiscountTransData.getTerminationFlag();
        //按条件退出
        if (CommonConstant.MCHNT_FEE_EXIT_UNDER_CONDITION.equals(terminationFlag)) {

            /* 单个商户优惠交易笔数上限 */
            BigDecimal quantityLimit = new BigDecimal(mcMchntFeeDiscountTransData.getQuantityLimit());
            /* 单个商户优惠交易金额上限 */
            BigDecimal amountLimit = new BigDecimal(mcMchntFeeDiscountTransData.getAmountLimit());
            if (null != tmStatMfdCriteria.getMrctDisUpLmtVal() && !"".equals(tmStatMfdCriteria.getMrctDisUpLmtVal())) {
                rglog.info("营销活动<{}> 商户<{}> 达标统计表 商户优惠上限值 字段有值，直接使用字段值<{}> 作为上限，无需通过计算规则重新计算!", mcNo, mchntNo, mcMchntFeeDiscountTransData.getMrctDisUpLmtVal());
                amountLimit = new BigDecimal(tmStatMfdCriteria.getMrctDisUpLmtVal());
            } else {
            }
            /* 单个商户手续费优惠额上限 */
            BigDecimal feeLimit = new BigDecimal(mcMchntFeeDiscountTransData.getFeeLimit());

            rglog.info("机构<{}>营销活动<{}> 商户<{}> 开始进行单个商户退出条件层面额度是否达到上限判断...", instId, mcNo, mchntNo);
            //累计优惠笔数
            BigDecimal totalQtyAcc9999 = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTotalQtyAcc9999());
            //累计优惠金额
            BigDecimal totalAmtAcc9999 = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTotalAmtAcc9999());
            //累计交易金额
            BigDecimal txnAmtAcc9999 = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTxnAmtAcc9999());
            //手续费减免活动商户单日统计数据 规则为0-累计优惠笔数
            BigDecimal totalQtyAccDayZero = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTotalQtyAccZero());
            //手续费减免活动商户单日统计数据 规则为0-累计优惠金额
            BigDecimal totalAmtAccDayZero = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTotalAmtAccZero());
            //手续费减免活动商户单日统计数据 规则为0-累计交易金额
            BigDecimal txnAmtAccDayZero = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTxnAmtAccZero());
            //商户维度判断是否达到上限使用
            BigDecimal totalQtyAccMchnt = totalQtyAcc9999.add(totalQtyAccDayZero);
            BigDecimal totalAmtAccMchnt = totalAmtAcc9999.add(totalAmtAccDayZero);
            BigDecimal txnAmtAccMchnt = txnAmtAcc9999.add(txnAmtAccDayZero);

            if (quantityLimit.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO &&
                    totalQtyAccMchnt.compareTo(quantityLimit) >= CommonConstant.ZERO) {
                rglog.info("机构<{}> 营销活动<{}> 单个商户优惠交易笔数上限<{}> 商户已使用额度<{}> 单个商户退出条件已达到限额，调账不再回退额度",
                        instId, mcNo, quantityLimit, totalQtyAccMchnt);
                return false;
            }
            if (feeLimit.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO &&
                    totalAmtAccMchnt.compareTo(feeLimit) >= CommonConstant.ZERO) {
                rglog.info("机构<{}> 营销活动<{}> 单个商户优惠交易手续费上限<{}> 商户已使用额度<{}> 单个商户退出条件已达到限额，调账不再回退额度",
                        instId, mcNo, feeLimit, totalAmtAccMchnt);
                return false;
            }

            if (amountLimit.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO &&
                    txnAmtAccMchnt.compareTo(amountLimit) >= CommonConstant.ZERO) {
                rglog.info("机构<{}> 营销活动<{}> 单个商户优惠交易金额上限<{}> 商户已使用额度<{}> 单个商户退出条件已达到限额，调账不再回退额度",
                        instId, mcNo, amountLimit, txnAmtAccMchnt);
                return false;
            }
        }

        /* 判断活动预算资金是否达到上限 */
        //总预算
        BigDecimal budget = new BigDecimal(mcMchntFeeDiscountTransData.getBudget());
        if (budget.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO) {
            //总预算累计消耗金额
            BigDecimal mcTotalAmtAcc = new BigDecimal(mcMchntFeeDiscountTransData.getMcTotalAmtAcc());
            if (mcTotalAmtAcc.compareTo(budget) >= CommonConstant.ZERO) {
                rglog.info("营销活动<{}>已累计优惠金额<{}> 活动总预算<{}> 达到额度值，不回退额度", mcMchntFeeDiscountTransData.getMcNo(), mcMchntFeeDiscountTransData.getMchntFeeDiscount(), mcMchntFeeDiscountTransData.getBudget());
                return false;
            }
        } else {
            rglog.info("默认预算资金无上限,不判断是否达到预算资金");
        }

        rglog.info("机构<{}>营销活动<{}> 规则<{}> 商户<{}> 各额度均未达到上限，需要回退额度", instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mchntNo);

        return true;
    }

    /**
     * 存量商户根据活动编号获取手续费减免类营销活动规则信息表
     *
     * @param instId 法人机构号
     * @param mcNo   营销活动编号
     * @return cc.rengu.igas.momp.common.entity.TMMcMchntFeeDiscountRuleInfo 商户手续费减免类营销活动规则信息表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/9/23 18:01
     */
    private List<TMMcMchntFeeDiscountRuleInfo> getMchntFeeDiscountMcRuleInfo(String instId, String mcNo) throws Exception {

        McRuleInfoMapper mcRuleInfoMapper = new McRuleInfoMapperImpl();
        return mcRuleInfoMapper.selectMchntFeeDiscountRuleInfoList(instId, mcNo);
    }

    /**
     * 获取商户手续费营销活动的活动规则对应的计算规则
     *
     * @param instId 法人机构号
     * @param ruleNo 规则编号
     * @return cc.rengu.igas.momp.common.entity.TMPlatCalRule 计算规则码表
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/9/23 17:27
     */
    private TMPlatCalRule selectCalculationRuleInfoByPK(String instId, String ruleNo) throws Exception {

        TMPlatCalRuleMapper tmPlatCalRuleMapper = new TMPlatCalRuleMapperImpl();
        return tmPlatCalRuleMapper.selectCalculationRuleInfoByPrimaryKey(instId, ruleNo);
    }

    /**
     * 根据计算规则计算当前商户手续费优惠限额
     *
     * @throws Exception 异常信息
     * @author liujinan
     * @date 2020/9/23 17:27
     */
    private String calculateMchntFeeDiscountLimit(String instId, String mchntNo, String ruleType, String nowCriteriaValue) throws Exception {

        String month = DateUtil.getFutureMonDay(CommonConstant.MINUS_ONE).substring(0, 6);
        rglog.debug("INST_ID=<{}>, MCHNT_NO=<{}>, MONTH=<{}>", instId, mchntNo, month);

        //商户上月日均余额直接取达标统计表中的当前统计值
        String mchntDeposit = nowCriteriaValue;

        BigDecimal TWO = new BigDecimal("2");
        BigDecimal HUNDARD_1 = new BigDecimal("125");
        BigDecimal HUNDARD_5 = new BigDecimal("500");
        BigDecimal THOUSAND_30 = new BigDecimal("30000");
        BigDecimal THOUSAND_50 = new BigDecimal("50000");
        BigDecimal THOUSAND_100 = new BigDecimal("100000");

        BigDecimal deposit = new BigDecimal(mchntDeposit).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        BigDecimal tenThousand = new BigDecimal("10000").setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        BigDecimal discountLimit;

        if (null != ruleType) {
            switch (FeeCalTypeEnum.getByValue(ruleType)) {
                case TYPE_2:
                    /* 上月日均存款万位取整+3万 */
                    discountLimit = deposit.remainder(tenThousand).add(THOUSAND_30);
                    break;
                case TYPE_3:
                    /* 上月日均存款*2+3万 */
                    discountLimit = deposit.multiply(TWO).add(THOUSAND_30);
                    break;
                case TYPE_4:
                    /* 上月日均存款万位取整+5万 */
                    discountLimit = deposit.remainder(tenThousand).add(THOUSAND_50);
                    break;
                case TYPE_5:
                    /* 上月日均存款*2+5万 */
                    discountLimit = deposit.multiply(TWO).add(THOUSAND_50);
                    break;
                case TYPE_6:
                    /* 上月日均存款每10万优惠125元 */
                    discountLimit = deposit.divide(THOUSAND_100).multiply(HUNDARD_1);
                    break;
                case TYPE_7:
                    /* 上月日均存款每10万优惠500元 */
                    discountLimit = deposit.divide(THOUSAND_100).multiply(HUNDARD_5);
                    break;
                case TYPE_8:
                    /* 上月日均存款 */
                    discountLimit = deposit;
                    break;
                case TYPE_9:
                    /* 上月日均存款每万元取整*2+3万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每万元*2+3万", ruleType);
                    discountLimit = deposit.divideToIntegralValue(tenThousand).multiply(TWO).multiply(tenThousand).add(THOUSAND_30);
                    break;
                case TYPE_10:
                    /* 上月日均存款每万元*2+5万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每万元*2+5万", ruleType);
                    discountLimit = deposit.divideToIntegralValue(tenThousand).multiply(TWO).multiply(tenThousand).add(THOUSAND_50);
                    break;
                case TYPE_11:
                    /* 上月日均存款每十万元*2+3万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每十万元*2+3万", ruleType);
                    discountLimit = deposit.divideToIntegralValue(THOUSAND_100).multiply(THOUSAND_100).multiply(TWO).add(THOUSAND_30);
                    break;
                case TYPE_12:
                    /* 上月日均存款每十万元*2+5万 */
                    rglog.info("手续费计算规则类型 <{}> 上月日均存款每十万元*2+5万", ruleType);
                    discountLimit = deposit.divideToIntegralValue(THOUSAND_100).multiply(THOUSAND_100).multiply(TWO).add(THOUSAND_50);
                    break;
                default:
                    discountLimit = BigDecimal.ZERO;
            }
            rglog.info("DISCOUNT_LIMIT=<{}>", discountLimit.setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
            return discountLimit.toString();
        } else {
            return CommonConstant.ZERO_AMOUNT;
        }
    }

    /**
     * 取商户手续费优惠类营销活动各维度统计数据
     *
     * @param mcMchntFeeDiscountTransData
     * @return int 返回码
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/9/25 20:22
     */
    private void fetchAllMchntFeeDiscountMcQuotaData(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, TMStatMfdCriteria tmStatMfdCriteria) throws Exception {

        //规则维度批量处理状态
        int batchStatus = CommonConstant.FLAG_NOT_SET;
        int batchStatus_stat_mfd = CommonConstant.FLAG_NOT_SET;
        String instId = tmStatMfdCriteria.getInstId();
        String mcNo = tmStatMfdCriteria.getMcNo();
        String mchntNo = tmStatMfdCriteria.getMchntNo();
        String periodStartDate = tmStatMfdCriteria.getPeriodStartDate();
        String periodEndDate = tmStatMfdCriteria.getPeriodEndDate();
        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        String lastSecondDate = DateUtil.getBaseDateOffsetDay(lastDate, CommonConstant.MINUS_ONE);

        /* 商户取营销活动规则信息 */
        List<TMMcMchntFeeDiscountRuleInfo> tmMcMchntFeeDiscountRuleInfoList = getMchntFeeDiscountMcRuleInfo(instId, mcNo);
        if (null == tmMcMchntFeeDiscountRuleInfoList || tmMcMchntFeeDiscountRuleInfoList.isEmpty()) {
            /* 未取到营销活动规则信息! */
            rglog.info("获取机构<{}>的营销活动<{}>营销活动规则信息失败!", instId, mcNo);
            throw new BizException(RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespDesc());
        }

        /* 代码判断匹配到了哪条规则上 */
        TMMcMchntFeeDiscountRuleInfo tmMcMchntFeeDiscountRuleInfo;
        BigDecimal criteriaValue = new BigDecimal(tmStatMfdCriteria.getCriteriaValue()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

        List<TMMcMchntFeeDiscountRuleInfo> tmMcMchntFeeDiscountRuleInfoList1 = new ArrayList<>();
        for (TMMcMchntFeeDiscountRuleInfo tmMcMchntFeeDiscountRuleInfo1 : tmMcMchntFeeDiscountRuleInfoList) {

            BigDecimal floor = new BigDecimal(tmMcMchntFeeDiscountRuleInfo1.getCriteriaFloor()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            BigDecimal celling = new BigDecimal(tmMcMchntFeeDiscountRuleInfo1.getCriteriaCelling()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);

            /* 按照左包右不包原则判断 */
            if (CommonConstant.ZERO <= criteriaValue.compareTo(floor) && CommonConstant.ZERO > criteriaValue.compareTo(celling)) {
                tmMcMchntFeeDiscountRuleInfoList1.add(tmMcMchntFeeDiscountRuleInfo1);
            }
        }

        if (tmMcMchntFeeDiscountRuleInfoList1.isEmpty()) {
            /* 判断是否是因为当前统计指超过最高档规则上限,是的话按照最高档规则进行计算 */
            tmMcMchntFeeDiscountRuleInfo = tmMcMchntFeeDiscountRuleInfoList.stream().max(Comparator.comparing(TMMcMchntFeeDiscountRuleInfo::getRuleIndex)).get();
            BigDecimal celling = new BigDecimal(tmMcMchntFeeDiscountRuleInfo.getCriteriaCelling()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
            if (CommonConstant.ZERO >= celling.compareTo(criteriaValue)) {
                rglog.info("当前商户<{}>的达标统计值<{}>超过最高一档规则上限<{}>,按照该档规则计算!", mchntNo, criteriaValue.toString(), celling.toString());
            } else {
                rglog.info("获取机构<{}>的营销活动<{}>优惠规则信息匹配失败,无满足条件的规则!", instId, mcNo);
                throw new BizException(RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespCode(), RespCodeEnum.GET_MC_RULE_INFO_ERROR.getRespDesc());
            }
        } else {
            rglog.info("当前商户<{}>,营销活动<{}>符合的规则条数为<{}>,如果多余一条，则取规则号最大的!", mchntNo, mcNo, tmMcMchntFeeDiscountRuleInfoList1.size());
            if (CommonConstant.ONE != tmMcMchntFeeDiscountRuleInfoList1.size()) {
                /* 超过1条以上规则符合条件 */
                tmMcMchntFeeDiscountRuleInfo = tmMcMchntFeeDiscountRuleInfoList1.stream().max(Comparator.comparing(TMMcMchntFeeDiscountRuleInfo::getRuleIndex)).get();
            } else {
                tmMcMchntFeeDiscountRuleInfo = tmMcMchntFeeDiscountRuleInfoList1.get(CommonConstant.ZERO);
            }
        }
        convertMchntFeeDiscountMcRuleInfo(tmMcMchntFeeDiscountRuleInfo, mcMchntFeeDiscountTransData);
        //调账交易时，所对应的规则号
        String ruleIndex = tmMcMchntFeeDiscountRuleInfo.getRuleIndex();
        //查询营销活动信息
        rglog.info("获取营销活动<{}>基本信息", mcNo);
        TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo = getMchntFeeDiscountMcInfo(instId, mcNo);
        if (null == tmMcMchntFeeDiscountInfo) {
            rglog.error("机构<{}>的商户<{}>未获取到商户手续费优惠营销活动信息!", instId, mchntNo);
            throw new BizException(RespCodeEnum.GET_MONEY_OFF_MC_DETAIL_ERROR.getRespCode(), RespCodeEnum.GET_MONEY_OFF_MC_DETAIL_ERROR.getRespDesc());
        }
        convertMchntFeeDiscountMcInfo(tmMcMchntFeeDiscountInfo, mcMchntFeeDiscountTransData);

        String mcStartDate = tmMcMchntFeeDiscountInfo.getMcStartDate();
        String mcType = tmMcMchntFeeDiscountInfo.getMcType();

        /*------------------------------------------------查询营销活动商户维度汇总数据------------------------------------*/
        /* 查询商户手续费优惠营销活动商户统计表数据  查询具体规则维度的统计数值*/
        TMStatMfdMchnt tmStatMfdMchnt = selectMchntFeeDiscountMchntStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, periodStartDate, periodEndDate);
        if (null == tmStatMfdMchnt) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动商户统计表数据查询失败!", globalInstId, mcNo, ruleIndex);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfdMchnt = new TMStatMfdMchnt();
            tmStatMfdMchnt.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);

        }

        /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据*/
        TMStatMfdMchntDay tmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, globalTxnDate);
        if (null == tmStatMfdMchntDay) {
            rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
            tmStatMfdMchntDay = new TMStatMfdMchntDay();
            tmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        /* 查询商户手续费优惠营销活动商户单日统计表数据  规则为0的数据*/
        TMStatMfdMchntDay tmStatMfdMchntDayRuleZero = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, mchntNo, globalTxnDate);
        if (null == tmStatMfdMchntDayRuleZero) {
            rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero = new TMStatMfdMchntDay();
            tmStatMfdMchntDayRuleZero.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDayRuleZero.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        /* 查询商户手续费优惠营销活动商户统计表数据  查询规则为9999的数据，这个统计的是营销活动配置商户退出条件时，统计周期内的所有规则的统计值*/
        TMStatMfdMchnt tmStatMfdMchnt9999 = selectNowPeriodDateTMStatMfdMchnt(instId, mcNo, CommonConstant.RULE_NINE, mchntNo, globalTxnDate);
        if (null == tmStatMfdMchnt9999) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动商户统计表数据查询失败!", globalInstId, mcNo, CommonConstant.RULE_NINE);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfdMchnt9999 = new TMStatMfdMchnt();
            tmStatMfdMchnt9999.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt9999.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt9999.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt9999.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }
        String batchDate;
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        String statPrimaryKey = "FeeMchnt" + instId + "_" + mcNo;
        TMStatBak tmStatBak = selectTMStatBakByStatPrimaryKey(globalInstId, mcType, statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //获取的数据累加到活动统计中
            /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据*/
            TMStatMfdMchntDay newtmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, batchDate);
            if (null == newtmStatMfdMchntDay) {
                rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
                newtmStatMfdMchntDay = new TMStatMfdMchntDay();
                newtmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            /* 查询商户手续费优惠营销活动商户单日统计表数据  规则为0的数据*/
            TMStatMfdMchntDay newtmStatMfdMchntDayRuleZero = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, mchntNo, batchDate);
            if (null == newtmStatMfdMchntDayRuleZero) {
                rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero = new TMStatMfdMchntDay();
                newtmStatMfdMchntDayRuleZero.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDayRuleZero.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            //将单日统计表的数据累加到周期数据上
            if (DateUtil.compareDate(batchDate, periodStartDate) < 0) {
                rglog.error("获取日期<{}>的单日统计不属于在本统计周期中，不需要累加到商户统计表!", batchDate);
            } else {
                rglog.error("获取日期<{}>的单日统计属于在本统计周期中，需要累加到商户统计表!", batchDate);
                copyMchntStatMfdData(tmStatMfdMchnt, newtmStatMfdMchntDay);
                copyMchntStatMfdData(tmStatMfdMchnt9999, newtmStatMfdMchntDayRuleZero);
            }
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }

        /*------------------------------------------------查询营销活动维度汇总数据------------------------------------*/
        /* 查询商户手续费优惠营销活动统计表数据  规则为0的数据*/
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        statPrimaryKey = "Fee" + instId + "_" + mcNo;
        tmStatBak = selectTMStatBakByStatPrimaryKey(instId, McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode(), statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        TMStatMfd tmStatMfd = selectMchntFeeDiscountStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
        if (null == tmStatMfd) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动统计表数据查询失败!", globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfd = new TMStatMfd();
            tmStatMfd.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }

        /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
        TMStatMfdDay tmStatMfdDay = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, globalTxnDate);
        if (null == tmStatMfdDay) {
            rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, ruleIndex);
            tmStatMfdDay = new TMStatMfdDay();
            tmStatMfdDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //循环获取单日统计表数据并累加
            /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
            TMStatMfdDay tmStatMfdDay2 = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT, batchDate);
            if (null == tmStatMfdDay2) {
                rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2 = new TMStatMfdDay();
                tmStatMfdDay2.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay2.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            copyStatMfdData(tmStatMfd, tmStatMfdDay2);
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }


        //更新本笔交易累计金额
        List<TMStatMfdDay> newStatMfdDayList = statMfdDayList.stream().filter(item -> item.getInstId().equals(instId) && item.getMcNo().equals(mcNo)).collect(Collectors.toList());
        //存在本笔交易同一活动数据
        if (newStatMfdDayList.size() > 0) {
            //全局变量手续费营销活动单日统计表数据更新已优惠金额
            TMStatMfdDay tmStatMfdToday = newStatMfdDayList.get(0);
            BigDecimal dayTotalAmtAcc = new BigDecimal(tmStatMfdToday.getTotalAmtAcc());
            statMfdDayList.stream().filter(item -> item.getInstId().equals(instId) && item.getMcNo().equals(mcNo)).collect(Collectors.toList()).get(0).setTotalAmtAcc(dayTotalAmtAcc.add(new BigDecimal(mcMchntFeeDiscountTransData.getMchntFeeDiscount())).toString());

        } else {//如果不存在 将子订单set
            TMStatMfdDay tmStatMfdToday = new TMStatMfdDay();
            tmStatMfdToday.setTotalAmtAcc(mcMchntFeeDiscountTransData.getMchntFeeDiscount());
            tmStatMfdToday.setInstId(instId);
            tmStatMfdToday.setMcNo(mcNo);
            statMfdDayList.add(tmStatMfdToday);
        }

        copyMchntFeeDiscountMchntStatData(tmStatMfdMchnt, mcMchntFeeDiscountTransData);
        copyMchntFeeDiscountMchntDayStatData(tmStatMfdMchntDay, mcMchntFeeDiscountTransData);
        copyMchntFeeDiscountMchntStat9999Data(tmStatMfdMchnt9999, mcMchntFeeDiscountTransData);
        copyMchntFeeDiscountMchntDayZeroStatData(tmStatMfdMchntDayRuleZero, mcMchntFeeDiscountTransData);
        copyMchntFeeDiscountZeroStatData(tmStatMfd, tmStatMfdDay, mcMchntFeeDiscountTransData);

    }

    /**
     * 手续费减免活动商户统计数据赋值
     *
     * @param tmStatMfdMchnt              手续费减免活动商户统计表
     * @param mcMchntFeeDiscountTransData 操作对象
     * @author liujinan
     * @since 2020/6/5 11:23
     */
    private void copyMchntFeeDiscountMchntStatData(TMStatMfdMchnt tmStatMfdMchnt, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 手续费减免活动商户统计-累计优惠笔数 */
        mcMchntFeeDiscountTransData.setMchntTotalQtyAcc(tmStatMfdMchnt.getTotalQtyAcc());
        /* 手续费减免活动商户统计-累计优惠金额 */
        mcMchntFeeDiscountTransData.setMchntTotalAmtAcc(tmStatMfdMchnt.getTotalAmtAcc());
        /* 手续费减免活动商户统计-累计交易笔数 */
        mcMchntFeeDiscountTransData.setMchntTxnQtyAcc(tmStatMfdMchnt.getTxnQtyAcc());
        /* 手续费减免活动商户统计-累计交易金额 */
        mcMchntFeeDiscountTransData.setMchntTxnAmtAcc(tmStatMfdMchnt.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动商户单日统计数据赋值
     *
     * @param tmStatMfdMchntDay           手续费减免活动商户单日统计表
     * @param mcMchntFeeDiscountTransData 操作对象
     * @author liujinan
     * @since 2020/6/5 11:22
     */
    private void copyMchntFeeDiscountMchntDayStatData(TMStatMfdMchntDay tmStatMfdMchntDay, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 手续费减免活动商户单日统计数据-累计优惠笔数 */
        mcMchntFeeDiscountTransData.setMchntDayTotalQtyAcc(tmStatMfdMchntDay.getTotalQtyAcc());
        /* 手续费减免活动商户单日统计数据-累计优惠金额 */
        mcMchntFeeDiscountTransData.setMchntDayTotalAmtAcc(tmStatMfdMchntDay.getTotalAmtAcc());
        /* 手续费减免活动商户单日统计数据-累计交易笔数 */
        mcMchntFeeDiscountTransData.setMchntDayTxnQtyAcc(tmStatMfdMchntDay.getTxnQtyAcc());
        /* 手续费减免活动商户单日统计数据-累计交易金额 */
        mcMchntFeeDiscountTransData.setMchntDayTxnAmtAcc(tmStatMfdMchntDay.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动商户统计数据(商户维度)赋值
     *
     * @param tmStatMfdMchnt 手续费减免活动商户统计表
     * @author liujinan
     * @since 2020/9/24 11:23
     */
    private void copyMchntFeeDiscountMchntStat9999Data(TMStatMfdMchnt tmStatMfdMchnt, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 总预算累计优惠笔数 */
        mcMchntFeeDiscountTransData.setMchntTotalQtyAcc9999(tmStatMfdMchnt.getTotalQtyAcc());
        /* 总预算累计优惠金额 */
        mcMchntFeeDiscountTransData.setMchntTotalAmtAcc9999(tmStatMfdMchnt.getTotalAmtAcc());
        /* 总预算累计交易笔数 */
        mcMchntFeeDiscountTransData.setMchntTxnQtyAcc9999(tmStatMfdMchnt.getTxnQtyAcc());
        /* 总预算累计交易金额 */
        mcMchntFeeDiscountTransData.setMchntTxnAmtAcc9999(tmStatMfdMchnt.getTxnAmtAcc());
    }

    /**
     * 手续费减免活动商户单日统计数据赋值 规则为0的统计数据
     *
     * @param tmStatMfdMchntDay           手续费减免活动商户单日统计表
     * @param mcMchntFeeDiscountTransData 操作对象
     * @author liujinan
     * @since 2020/9/25 11:22
     */
    private void copyMchntFeeDiscountMchntDayZeroStatData(TMStatMfdMchntDay tmStatMfdMchntDay, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 手续费减免活动商户单日统计数据-累计优惠笔数 */
        mcMchntFeeDiscountTransData.setMchntDayTotalQtyAccZero(tmStatMfdMchntDay.getTotalQtyAcc());
        /* 手续费减免活动商户单日统计数据-累计优惠金额 */
        mcMchntFeeDiscountTransData.setMchntDayTotalAmtAccZero(tmStatMfdMchntDay.getTotalAmtAcc());
        /* 手续费减免活动商户单日统计数据-累计交易笔数 */
        mcMchntFeeDiscountTransData.setMchntDayTxnQtyAccZero(tmStatMfdMchntDay.getTxnQtyAcc());
        /* 手续费减免活动商户单日统计数据-累计交易金额 */
        mcMchntFeeDiscountTransData.setMchntDayTxnAmtAccZero(tmStatMfdMchntDay.getTxnAmtAcc());
    }

    /**
     * 使用主键取手续费减免活动商户统计表单条数据
     *
     * @param instId
     * @param mcNo
     * @param ruleIndex
     * @param mchntNo
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchnt
     * @throws Exception
     * @author liujinan
     * @date 2020/9/15
     */
    private TMStatMfdMchnt selectNowPeriodDateTMStatMfdMchnt(String instId, String mcNo, String ruleIndex, String mchntNo, String txnDate) throws Exception {

        TMStatMfdMchntMapper tmStatMfdMchntMapper = new TMStatMfdMchntMapperImpl();
        return tmStatMfdMchntMapper.selectNowPeriodDateTMStatMfdMchnt(instId, mcNo, ruleIndex, mchntNo, txnDate);
    }

    /**
     * 使用主键取手续费减免活动商户统计表单条数据
     *
     * @param instId          法人机构号
     * @param mcNo            营销活动编号
     * @param ruleIndex       规则顺序号
     * @param mchntNo         商户编号
     * @param periodStartDate 统计周期起始日期
     * @param periodEndDate   统计周期结束日期
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchnt 手续费减免活动商户统计表
     * @throws Exception 异常信息
     * @author Jinan Liu
     * @since 2020/4/20 23:40
     */
    private TMStatMfdMchnt selectMchntFeeDiscountMchntStatisticsByPK(String instId, String mcNo, String ruleIndex, String mchntNo, String periodStartDate, String periodEndDate) throws Exception {

        TMStatMfdMchntMapper tmStatMfdMchntMapper = new TMStatMfdMchntMapperImpl();
        return tmStatMfdMchntMapper.selectMchntFeeDiscountMchntStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, periodStartDate, periodEndDate);
    }

    /**
     * 使用营销活动商户信息对象获取商户手续费优惠类营销活动基本信息
     *
     * @param instId 法人机构号
     * @param mcNo   营销活动编号
     * @return cc.rengu.igas.momp.common.entity.TMMcMchntFeeDiscountInfo 商户手续费减免类营销活动信息表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/9/25 14:14
     */
    private TMMcMchntFeeDiscountInfo getMchntFeeDiscountMcInfo(String instId, String mcNo) throws Exception {

        McDetailInfoMapper mcDetailInfoMapper = new McDetailInfoMapperImpl();
        return mcDetailInfoMapper.selectMchntFeeDiscountMcDetailInfo(instId, mcNo);
    }

    /**
     * 商户手续费优惠营销活动规则信息转换
     *
     * @param tmMcMchntFeeDiscountRuleInfo 商户手续费减免类营销活动规则信息表
     * @author liujinan
     * @since 2020/4/20 20:47
     */
    private void convertMchntFeeDiscountMcRuleInfo(TMMcMchntFeeDiscountRuleInfo tmMcMchntFeeDiscountRuleInfo, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {

        /* 顺序号 */
        mcMchntFeeDiscountTransData.setRuleIndex(tmMcMchntFeeDiscountRuleInfo.getRuleIndex());
        /* 控制下限 */
        mcMchntFeeDiscountTransData.setCriteriaFloor(tmMcMchntFeeDiscountRuleInfo.getCriteriaFloor());
        /* 控制上限 */
        mcMchntFeeDiscountTransData.setCriteriaCelling(tmMcMchntFeeDiscountRuleInfo.getCriteriaCelling());
        /* 优惠周期 */
        mcMchntFeeDiscountTransData.setDiscountPeriod(tmMcMchntFeeDiscountRuleInfo.getDiscountPeriod());
        /* 优惠类型 */
        mcMchntFeeDiscountTransData.setDiscountType(tmMcMchntFeeDiscountRuleInfo.getDiscountType());
        /* 优惠力度 */
        mcMchntFeeDiscountTransData.setDiscount(tmMcMchntFeeDiscountRuleInfo.getDiscount());
        /* 计算规则编号 */
        mcMchntFeeDiscountTransData.setCalRuleNo(tmMcMchntFeeDiscountRuleInfo.getCalRuleNo());
        /* 优惠上限 */
        mcMchntFeeDiscountTransData.setDiscountLimit(tmMcMchntFeeDiscountRuleInfo.getDiscountLimit());
    }

    /**
     * 商户手续费优惠营销活动信息转换
     *
     * @param tmMcMchntFeeDiscountInfo 商户手续费减免类营销活动信息表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/9/25 17:14
     */
    private void convertMchntFeeDiscountMcInfo(TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) throws Exception {

        /* 营销活动编号 */
        mcMchntFeeDiscountTransData.setMcNo(tmMcMchntFeeDiscountInfo.getMcNo());
        /* 营销活动名称 */
        mcMchntFeeDiscountTransData.setMcName(tmMcMchntFeeDiscountInfo.getMcName());
        /* 营销活动类型 */
        mcMchntFeeDiscountTransData.setMcType(tmMcMchntFeeDiscountInfo.getMcType());
        /* 营销活动状态 */
        mcMchntFeeDiscountTransData.setMcStatus(tmMcMchntFeeDiscountInfo.getMcStatus());
        /* 活动起始日期 */
        mcMchntFeeDiscountTransData.setMcStartDate(tmMcMchntFeeDiscountInfo.getMcStartDate());
        /* 活动截止日期 */
        mcMchntFeeDiscountTransData.setMcEndDate(tmMcMchntFeeDiscountInfo.getMcEndDate());
        /* 活动结束日期 */
        mcMchntFeeDiscountTransData.setMcActualEndDate(tmMcMchntFeeDiscountInfo.getMcActualEndDate());
        /* 存量商户达标条件 */
        mcMchntFeeDiscountTransData.setStockMchntFlag(tmMcMchntFeeDiscountInfo.getStockMchntFlag());
        /* 存量商户支持类型 */
        mcMchntFeeDiscountTransData.setStockMchntType(tmMcMchntFeeDiscountInfo.getStockMchntType());
        /* 有效交易下限 */
        mcMchntFeeDiscountTransData.setEffectiveLimit(tmMcMchntFeeDiscountInfo.getEffectiveLimit());
        /* 新增商户活动标志 */
        mcMchntFeeDiscountTransData.setNewMchntFlag(tmMcMchntFeeDiscountInfo.getNewMchntFlag());
        /* 新增商户免手续费周期 */
        mcMchntFeeDiscountTransData.setNewMchntPeriod(tmMcMchntFeeDiscountInfo.getNewMchntPeriod());
        /* 新增商户周期顺延标志 */
        mcMchntFeeDiscountTransData.setPostponeFlag(tmMcMchntFeeDiscountInfo.getPostponeFlag());
        /* 达标前手续费优惠规则 */
        mcMchntFeeDiscountTransData.setBeforeFlag(tmMcMchntFeeDiscountInfo.getBeforeFlag());
        /* 达标后手续费优惠规则 */
        mcMchntFeeDiscountTransData.setAfterFlag(tmMcMchntFeeDiscountInfo.getAfterFlag());
        /* 优惠退出标志 */
        mcMchntFeeDiscountTransData.setTerminationFlag(tmMcMchntFeeDiscountInfo.getTerminationFlag());
        /* 统计周期 */
        mcMchntFeeDiscountTransData.setStatPeriod(tmMcMchntFeeDiscountInfo.getStatPeriod());
        /* 单个商户优惠交易笔数上限 */
        mcMchntFeeDiscountTransData.setQuantityLimit(tmMcMchntFeeDiscountInfo.getQuantityLimit());
        /* 单个商户优惠交易金额上限 */
        mcMchntFeeDiscountTransData.setAmountLimit(tmMcMchntFeeDiscountInfo.getAmountLimit());
        /* 单个商户手续费优惠额上限 */
        mcMchntFeeDiscountTransData.setFeeLimit(tmMcMchntFeeDiscountInfo.getFeeLimit());
        /* 新商户优惠额上限 */
        mcMchntFeeDiscountTransData.setNewMchntAmountLimit(tmMcMchntFeeDiscountInfo.getNewMchntAmountLimit());
        /* 营销活动预算 */
        mcMchntFeeDiscountTransData.setBudget(tmMcMchntFeeDiscountInfo.getBudget());
    }

    /**
     * 使用主键取手续费减免活动商户单日统计表单条数据
     *
     * @param instId    法人机构号
     * @param mcNo      营销活动编号
     * @param ruleIndex 规则顺序号
     * @param mchntNo   商户编号
     * @param txnDate   交易日期
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdMchntDay 手续费减免活动商户单日统计表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/8/29 15:23
     */
    private TMStatMfdMchntDay selectMchntFeeDiscountMchntDayStatisticsByPK(String instId, String mcNo, String ruleIndex, String mchntNo, String txnDate) throws Exception {

        TMStatMfdMchntDayMapper tmStatMfdMchntDayMapper = new TMStatMfdMchntDayMapperImpl();
        return tmStatMfdMchntDayMapper.selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, txnDate);
    }

    /**
     * 使用主键取手续费减免活动单日统计表单条数据
     *
     * @param instId    法人机构号
     * @param mcNo      营销活动编号
     * @param ruleIndex 规则顺序号
     * @param transDate 交易日期
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdDay 手续费减免活动单日统计表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/8/29 15:23
     */
    private TMStatMfdDay selectMchntFeeDiscountDayStatisticsByPK(String instId, String mcNo, String ruleIndex, String transDate) throws Exception {

        TMStatMfdDayMapper tmStatMfdDayMapper = new TMStatMfdDayMapperImpl();
        return tmStatMfdDayMapper.selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, ruleIndex, transDate);
    }

    /**
     * 使用主键取手续费减免活动统计表单条数据
     *
     * @param instId    法人机构编号
     * @param mcNo      营销活动编号
     * @param ruleIndex 规则顺序号
     * @return cc.rengu.igas.momp.common.entity.TMStatMfd 手续费减免活动统计表
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/10/20 15:23
     */
    private TMStatMfd selectMchntFeeDiscountStatisticsByPK(String instId, String mcNo, String ruleIndex) throws Exception {

        TMStatMfdMapper tmStatMfdMapper = new TMStatMfdMapperImpl();
        return tmStatMfdMapper.selectMchntFeeDiscountStatisticsByPK(instId, mcNo, ruleIndex);
    }

    /**
     * 手续费减免活动统计数据赋值 规则为0的统计数据
     *
     * @param tmStatMfd    手续费减免活动统计表
     * @param tmStatMfdDay 手续费减免活动单日统计表
     * @author JL Pang
     * @since 2020/10/18 11:22
     */
    private void copyMchntFeeDiscountZeroStatData(TMStatMfd tmStatMfd, TMStatMfdDay tmStatMfdDay, McMchntFeeDiscountTransData mcMchntFeeDiscountTransData) {
        /* 手续费减免活动统计数据-总预算消耗金额 */
        mcMchntFeeDiscountTransData.setMcTotalAmtAcc(new BigDecimal(tmStatMfd.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTotalAmtAcc())).toString());

    }

    /**
     * 取商户手续费优惠类营销活动各维度统计数据
     *
     * @param mcMchntFeeDiscountTransData
     * @return int 返回码
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2020/10/20 20:22
     */
    private void fetchNewMchntFeeDiscountMcQuotaData(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, TMStatMfdCriteria tmStatMfdCriteria) throws Exception {

        //规则维度批量处理状态
        int batchStatus_stat_mfd = CommonConstant.FLAG_NOT_SET;
        int batchStatus_stat_mfd_mchnt = CommonConstant.FLAG_NOT_SET;
        String instId = tmStatMfdCriteria.getInstId();
        String mcNo = tmStatMfdCriteria.getMcNo();
        String mchntNo = tmStatMfdCriteria.getMchntNo();
        String periodStartDate = tmStatMfdCriteria.getPeriodStartDate();
        String periodEndDate = tmStatMfdCriteria.getPeriodEndDate();
        String lastDate = DateUtil.getBaseDateOffsetDay(globalTxnDate, CommonConstant.MINUS_ONE);
        String lastSecondDate = DateUtil.getBaseDateOffsetDay(lastDate, CommonConstant.MINUS_ONE);
        String ruleIndex = CommonConstant.ZERO_COMMON_CONSTANT;
        String mfdCriteriaCreateTimeTmp = tmStatMfdCriteria.getCreateTime();
        String mfdCriteriaCreateTime = mfdCriteriaCreateTimeTmp.substring(0, 4) + mfdCriteriaCreateTimeTmp.substring(5, 7) + mfdCriteriaCreateTimeTmp.substring(8, 10);

        rglog.info("获取营销活动<{}>基本信息", mcNo);
        TMMcMchntFeeDiscountInfo tmMcMchntFeeDiscountInfo = getMchntFeeDiscountMcInfo(instId, mcNo);
        if (null == tmMcMchntFeeDiscountInfo) {
            rglog.error("机构<{}>的商户<{}>未获取到商户手续费优惠营销活动信息!", instId, mchntNo);
            throw new BizException(RespCodeEnum.GET_MONEY_OFF_MC_DETAIL_ERROR.getRespCode(), RespCodeEnum.GET_MONEY_OFF_MC_DETAIL_ERROR.getRespDesc());
        }
        convertMchntFeeDiscountMcInfo(tmMcMchntFeeDiscountInfo, mcMchntFeeDiscountTransData);

        String mcStartDate = tmMcMchntFeeDiscountInfo.getMcStartDate();
        String mcType = tmMcMchntFeeDiscountInfo.getMcType();

        /*------------------------------------------------查询营销活动商户维度汇总数据------------------------------------*/
        /* 查询商户手续费优惠营销活动商户统计表数据  查询具体规则维度的统计数值 新增商户的这个值应该为0*/
        TMStatMfdMchnt tmStatMfdMchnt = selectMchntFeeDiscountMchntStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, periodStartDate, periodEndDate);
        if (null == tmStatMfdMchnt) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动商户统计表数据查询失败!", globalInstId, mcNo, ruleIndex);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfdMchnt = new TMStatMfdMchnt();
            tmStatMfdMchnt.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchnt.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);

        }
        String batchDate;
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        String statPrimaryKey = "FeeMchnt" + instId + "_" + mcNo;
        TMStatBak tmStatBak = selectTMStatBakByStatPrimaryKey(globalInstId, mcType, statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = periodStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //获取的数据累加到活动统计中
            /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据*/
            TMStatMfdMchntDay newtmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, batchDate);
            if (null == newtmStatMfdMchntDay) {
                rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
                newtmStatMfdMchntDay = new TMStatMfdMchntDay();
                newtmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                newtmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            //将单日统计表的数据累加到周期数据上
            if (DateUtil.compareDate(batchDate, periodStartDate) < 0) {
                rglog.error("获取日期<{}>的单日统计不属于在本统计周期中，不需要累加到商户统计表!", batchDate);
            } else {
                rglog.error("获取日期<{}>的单日统计属于在本统计周期中，需要累加到商户统计表!", batchDate);
                copyMchntStatMfdData(tmStatMfdMchnt, newtmStatMfdMchntDay);
            }
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }
        /* 查询商户手续费优惠营销活动商户单日统计表数据 具体规则编号的数据 新增商户的这个值应该为0*/
        TMStatMfdMchntDay tmStatMfdMchntDay = selectMchntFeeDiscountMchntDayStatisticsByPK(instId, mcNo, ruleIndex, mchntNo, globalTxnDate);
        if (null == tmStatMfdMchntDay) {
            rglog.error("机构<{}> 商户<{}> 商户手续费优惠营销活动<{}> 规则<{}> 商户手续费优惠营销活动商户单日统计表数据查询失败!", instId, mchntNo, mcNo, ruleIndex);
            tmStatMfdMchntDay = new TMStatMfdMchntDay();
            tmStatMfdMchntDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdMchntDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }


        copyMchntFeeDiscountMchntStatData(tmStatMfdMchnt, mcMchntFeeDiscountTransData);
        copyMchntFeeDiscountMchntDayStatData(tmStatMfdMchntDay, mcMchntFeeDiscountTransData);

        /*------------------------------------------------查询营销活动维度汇总数据------------------------------------*/
        /* 查询商户手续费优惠营销活动统计表数据  规则为0的数据*/
        //查询统计信息备份表批次信息 查询营销活动信息表的批量处理情况即可
        statPrimaryKey = "Fee" + instId + "_" + mcNo;
        tmStatBak = selectTMStatBakByStatPrimaryKey(instId, McTypeEnum.MCHNT_FEE_DISCOUNT.getMcTypeCode(), statPrimaryKey);
        //批次表为空，从来没执行过批量任务
        if (null == tmStatBak) {
            //从来没执行过批量任务，则从活动开始的第一天开始取数据
            batchDate = mcStartDate;
        } else {
            batchDate = DateUtil.getBaseDateOffsetDay(tmStatBak.getBatchDate(), 1);
        }

        /* 查询商户手续费优惠营销活动统计表数据  规则为0的数据*/
        TMStatMfd tmStatMfd = selectMchntFeeDiscountStatisticsByPK(instId, mcNo, ruleIndex);
        if (null == tmStatMfd) {
            rglog.info("机构<{}>的营销活动<{}>的规则<{}>商户手续费优惠营销活动统计表数据查询失败!", globalInstId, mcNo, CommonConstant.ZERO_COMMON_CONSTANT);

            /* 取到0条数据,说明该营销活动还未产生统计值,按所有统计值都是0进行处理 */
            tmStatMfd = new TMStatMfd();
            tmStatMfd.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfd.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);

        }
        //批量处理的日期小于昨天的日期，则需要取之前的数据
        while (DateUtil.compareDate(batchDate, lastDate) <= 0) {
            //循环获取单日统计表数据并累加
            /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
            TMStatMfdDay tmStatMfdDay1 = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, ruleIndex, batchDate);
            if (null == tmStatMfdDay1) {
                rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, ruleIndex);
                tmStatMfdDay1 = new TMStatMfdDay();
                tmStatMfdDay1.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
                tmStatMfdDay1.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            }
            copyStatMfdData(tmStatMfd, tmStatMfdDay1);
            //将批次日期加一天继续判断
            batchDate = DateUtil.getBaseDateOffsetDay(batchDate, 1);
        }

        /* 查询商户手续费优惠营销活动单日统计表数据 规则为0的数据*/
        TMStatMfdDay tmStatMfdDay = selectMchntFeeDiscountDayStatisticsByPK(instId, mcNo, ruleIndex, globalTxnDate);
        if (null == tmStatMfdDay) {
            rglog.error("机构<{}>的商户手续费优惠营销活动<{}>的规则<{}> 手续费减免活动单日统计表 数据查询失败!", instId, mcNo, ruleIndex);
            tmStatMfdDay = new TMStatMfdDay();
            tmStatMfdDay.setTotalQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTotalAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnQtyAcc(CommonConstant.ZERO_COMMON_CONSTANT);
            tmStatMfdDay.setTxnAmtAcc(CommonConstant.ZERO_COMMON_CONSTANT);
        }


        //将累计优惠手续费金额赋值
        copyMchntFeeDiscountZeroStatData(tmStatMfd, tmStatMfdDay, mcMchntFeeDiscountTransData);
    }

    /**
     * 判断新商户是否达到额度限制
     *
     * @author liujinan
     * @date 2020/10/20 17:27
     */
    private Boolean judgeNewMchntIsReachLimit(McMchntFeeDiscountTransData mcMchntFeeDiscountTransData, TMStatMfdCriteria tmStatMfdCriteria) throws Exception {

        String instId = tmStatMfdCriteria.getInstId();
        String mcNo = tmStatMfdCriteria.getMcNo();
        String mchntNo = tmStatMfdCriteria.getMchntNo();

        //手续费减免活动商户统计 具体规则-累计优惠交易金额
        BigDecimal txnAmtAcc = new BigDecimal(mcMchntFeeDiscountTransData.getMchntTxnAmtAcc());
        //手续费减免活动商户单日统计数据 具体规则-累计优惠金额
        BigDecimal txnAmtAccDay = new BigDecimal(mcMchntFeeDiscountTransData.getMchntDayTxnAmtAcc());

        if (null != tmStatMfdCriteria.getMrctDisUpLmtVal() && !"".equals(tmStatMfdCriteria.getMrctDisUpLmtVal())) {
            rglog.info("营销活动<{}> 商户<{}> 达标统计表 商户优惠上限值 字段有值，直接使用字段值<{}> 作为上限，无需通过计算规则重新计算!", mcNo, mchntNo, mcMchntFeeDiscountTransData.getMrctDisUpLmtVal());
            mcMchntFeeDiscountTransData.setNewMchntAmountLimit(tmStatMfdCriteria.getMrctDisUpLmtVal());
        } else {
        }
        /* 判断新商户优惠上限是否超限 */
        BigDecimal discountLimit = new BigDecimal(mcMchntFeeDiscountTransData.getNewMchntAmountLimit()).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        //周期统计累计优惠交易金额 + 单日统计累计优惠交易金额
        BigDecimal totalDiscount = txnAmtAcc.add(txnAmtAccDay).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP);
        rglog.info("新商户周期内优惠上限<{}>,目前已优惠金额<{}>", discountLimit, totalDiscount);

        if (totalDiscount.compareTo(discountLimit) >= CommonConstant.ZERO) {
            /*超过限额，不需要回退额度，*/
            rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}> 新商户优惠交易额上限<{}> ，目前已优惠交易额<{}>，已超限额,不需要回退额度！", instId, mcNo, discountLimit, totalDiscount);
            return false;
        } else {
            /*未超过限额，需要回退额度，*/
            rglog.info("法人机构<{}>的商户手续费优惠营销活动<{}> 新商户优惠交易额上限<{}> ，目前已优惠交易额<{}>，未超限额,判断流程继续！", instId, mcNo, discountLimit, totalDiscount);
        }

        /* 判断活动预算资金是否达到上限 */
        //总预算
        BigDecimal budget = new BigDecimal(mcMchntFeeDiscountTransData.getBudget());
        if (budget.compareTo(BigDecimal.ZERO) > CommonConstant.ZERO) {
            //总预算累计消耗金额
            BigDecimal mcTotalAmtAcc = new BigDecimal(mcMchntFeeDiscountTransData.getMcTotalAmtAcc());
            if (mcTotalAmtAcc.compareTo(budget) >= CommonConstant.ZERO) {
                rglog.info("营销活动<{}>已累计优惠金额<{}> 活动总预算<{}> 达到额度值，不回退额度", mcMchntFeeDiscountTransData.getMcNo(), mcMchntFeeDiscountTransData.getMchntFeeDiscount(), mcMchntFeeDiscountTransData.getBudget());
                return false;
            }
        } else {
            rglog.info("默认预算资金无上限,不判断是否达到预算资金");
        }

        rglog.info("机构<{}>营销活动<{}> 规则<{}> 商户<{}> 各额度均未达到上限，需要回退额度", instId, mcNo, mcMchntFeeDiscountTransData.getRuleIndex(), mchntNo);
        return true;
    }

    /**
     * 更细手续费优惠达标数据统计表商户优惠退出状态
     *
     * @param tmStatMfdCriteria
     * @throws Exception 异常信息
     * @author liujinan
     * @since 2021-07-23 15:22
     */
    private void checkExitFlagAndUpdateTMStatMfdCriteria(TMStatMfdCriteria tmStatMfdCriteria) throws Exception {
        //更新营销活动手续费减免达标数据统计表优惠退出标志exit_discount_status置为0 -未退出
        tmStatMfdCriteria.setExitDiscountStatus(CommonConstant.MC_NOT_EXIT_FLAG);
        TMStatMfdCriteriaMapper tmStatMfdCriteriaMapper = new TMStatMfdCriteriaMapperImpl();
        int updateReturnCode = tmStatMfdCriteriaMapper.updateTMstatMfdCriteriaByPrimaryKey(tmStatMfdCriteria);
        if (updateReturnCode != 0) {
            rglog.error("机构<{}> 商户<{}> 营销活动编号<{}> 根据主键更新营销活动手续费减免达标数据统计表失败！",
                    tmStatMfdCriteria.getInstId(), tmStatMfdCriteria.getMchntNo(), tmStatMfdCriteria.getMcNo());
            throw new BizException(RespCodeEnum.DATABASE_OPR_ERROR.getRespCode(), RespCodeEnum.DATABASE_OPR_ERROR.getRespDesc());
        }
    }

    /**
     * 使用主键查询统计信息备份表最新一条数据
     *
     * @param instId
     * @param statType
     * @param statPrimaryKey
     * @return cc.rengu.igas.momp.common.entity.TMStatMfdPeriod
     * @throws Exception
     * @author liujinan
     * @date 2021/7/9
     */
    private TMStatBak selectTMStatBakByStatPrimaryKey(String instId, String statType, String statPrimaryKey) throws Exception {

        TMStatBakMapper tmStatBakMapper = new TMStatBakMapperImpl();
        return tmStatBakMapper.selectTMStatBakByStatPrimaryKey(instId, statType, statPrimaryKey);
    }

    /**
     * 手续费减免活动商户统计数据赋值
     *
     * @param tmStatMfdMchnt    手续费减免活动商户统计表
     * @param tmStatMfdMchntDay 手续费减免活动商户单日统计表
     * @author Jinan Liu
     * @since 2020/6/5 11:23
     */
    private void copyMchntStatMfdData(TMStatMfdMchnt tmStatMfdMchnt, TMStatMfdMchntDay tmStatMfdMchntDay) {

        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfdMchnt.setTotalQtyAcc(new BigDecimal(tmStatMfdMchnt.getTotalQtyAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTotalQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfdMchnt.setTotalAmtAcc(new BigDecimal(tmStatMfdMchnt.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTotalAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfdMchnt.setTxnQtyAcc(new BigDecimal(tmStatMfdMchnt.getTxnQtyAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTxnQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfdMchnt.setTxnAmtAcc(new BigDecimal(tmStatMfdMchnt.getTxnAmtAcc()).add(new BigDecimal(tmStatMfdMchntDay.getTxnAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
    }

    /**
     * 手续费减免活动统计数据赋值
     *
     * @param tmStatMfd    手续费减免活动统计表
     * @param tmStatMfdDay 手续费减免活动单日统计表
     * @author Jinan Liu
     * @since 2020/6/5 11:23
     */
    private void copyStatMfdData(TMStatMfd tmStatMfd, TMStatMfdDay tmStatMfdDay) {

        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfd.setTotalQtyAcc(new BigDecimal(tmStatMfd.getTotalQtyAcc()).add(new BigDecimal(tmStatMfdDay.getTotalQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfd.setTotalAmtAcc(new BigDecimal(tmStatMfd.getTotalAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTotalAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
        /* 营销活动单日累计-总预算累计消耗笔数 */
        tmStatMfd.setTxnQtyAcc(new BigDecimal(tmStatMfd.getTxnQtyAcc()).add(new BigDecimal(tmStatMfdDay.getTxnQtyAcc())).toString());
        /* 营销活动单日累计-总预算累计消耗金额 */
        tmStatMfd.setTxnAmtAcc(new BigDecimal(tmStatMfd.getTxnAmtAcc()).add(new BigDecimal(tmStatMfdDay.getTxnAmtAcc())).setScale(CommonConstant.DECIMAL_SCALE_TWO, RoundingMode.HALF_UP).toString());
    }

}
